| 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 serialization.summarize_ast; |
| 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/ast/visitor.dart'; |
| 10 import 'package:analyzer/dart/element/type.dart' show DartType; |
| 11 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 12 import 'package:analyzer/src/summary/format.dart'; |
| 13 import 'package:analyzer/src/summary/idl.dart'; |
| 14 import 'package:analyzer/src/summary/public_namespace_computer.dart'; |
| 15 import 'package:analyzer/src/summary/summarize_const_expr.dart'; |
| 16 |
| 17 /** |
| 18 * Serialize all the declarations in [compilationUnit] to an unlinked summary. |
| 19 */ |
| 20 UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit) { |
| 21 return new _SummarizeAstVisitor().serializeCompilationUnit(compilationUnit); |
| 22 } |
| 23 |
| 24 /** |
| 25 * Instances of this class keep track of intermediate state during |
| 26 * serialization of a single constant [Expression]. |
| 27 */ |
| 28 class _ConstExprSerializer extends AbstractConstExprSerializer { |
| 29 final _SummarizeAstVisitor visitor; |
| 30 |
| 31 /** |
| 32 * If the expression being serialized can contain closures, map whose |
| 33 * keys are the offsets of local function nodes representing those closures, |
| 34 * and whose values are indices of those local functions relative to their |
| 35 * siblings. |
| 36 */ |
| 37 final Map<int, int> localClosureIndexMap; |
| 38 |
| 39 /** |
| 40 * If the expression being serialized appears inside a function body, the name
s |
| 41 * of parameters that are in scope. Otherwise `null`. |
| 42 */ |
| 43 final Set<String> parameterNames; |
| 44 |
| 45 _ConstExprSerializer( |
| 46 this.visitor, this.localClosureIndexMap, this.parameterNames); |
| 47 |
| 48 @override |
| 49 bool isParameterName(String name) { |
| 50 return parameterNames?.contains(name) ?? false; |
| 51 } |
| 52 |
| 53 @override |
| 54 void serializeAnnotation(Annotation annotation) { |
| 55 if (annotation.arguments == null) { |
| 56 assert(annotation.constructorName == null); |
| 57 serialize(annotation.name); |
| 58 } else { |
| 59 Identifier name = annotation.name; |
| 60 EntityRefBuilder constructor; |
| 61 if (name is PrefixedIdentifier && annotation.constructorName == null) { |
| 62 constructor = |
| 63 serializeConstructorRef(null, name.prefix, null, name.identifier); |
| 64 } else { |
| 65 constructor = serializeConstructorRef( |
| 66 null, annotation.name, null, annotation.constructorName); |
| 67 } |
| 68 serializeInstanceCreation(constructor, annotation.arguments); |
| 69 } |
| 70 } |
| 71 |
| 72 @override |
| 73 EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName, |
| 74 TypeArgumentList typeArguments, SimpleIdentifier name) { |
| 75 EntityRefBuilder typeBuilder = serializeType(type, typeName, typeArguments); |
| 76 if (name == null) { |
| 77 return typeBuilder; |
| 78 } else { |
| 79 int nameRef = |
| 80 visitor.serializeReference(typeBuilder.reference, name.name); |
| 81 return new EntityRefBuilder( |
| 82 reference: nameRef, typeArguments: typeBuilder.typeArguments); |
| 83 } |
| 84 } |
| 85 |
| 86 @override |
| 87 List<int> serializeFunctionExpression(FunctionExpression functionExpression) { |
| 88 int localIndex; |
| 89 if (localClosureIndexMap == null) { |
| 90 return null; |
| 91 } else { |
| 92 localIndex = localClosureIndexMap[functionExpression.offset]; |
| 93 assert(localIndex != null); |
| 94 return <int>[0, localIndex]; |
| 95 } |
| 96 } |
| 97 |
| 98 EntityRefBuilder serializeIdentifier(Identifier identifier) { |
| 99 EntityRefBuilder b = new EntityRefBuilder(); |
| 100 if (identifier is SimpleIdentifier) { |
| 101 int index = visitor.serializeSimpleReference(identifier.name, |
| 102 allowTypeParameter: true); |
| 103 if (index < 0) { |
| 104 b.paramReference = -index; |
| 105 } else { |
| 106 b.reference = index; |
| 107 } |
| 108 } else if (identifier is PrefixedIdentifier) { |
| 109 int prefix = visitor.serializeSimpleReference(identifier.prefix.name); |
| 110 b.reference = |
| 111 visitor.serializeReference(prefix, identifier.identifier.name); |
| 112 } else { |
| 113 throw new StateError( |
| 114 'Unexpected identifier type: ${identifier.runtimeType}'); |
| 115 } |
| 116 return b; |
| 117 } |
| 118 |
| 119 @override |
| 120 EntityRefBuilder serializeIdentifierSequence(Expression expr) { |
| 121 if (expr is Identifier) { |
| 122 AstNode parent = expr.parent; |
| 123 if (parent is MethodInvocation && |
| 124 parent.methodName == expr && |
| 125 parent.target != null) { |
| 126 int targetId = serializeIdentifierSequence(parent.target).reference; |
| 127 int nameId = visitor.serializeReference(targetId, expr.name); |
| 128 return new EntityRefBuilder(reference: nameId); |
| 129 } |
| 130 return serializeIdentifier(expr); |
| 131 } |
| 132 if (expr is PropertyAccess) { |
| 133 int targetId = serializeIdentifierSequence(expr.target).reference; |
| 134 int nameId = visitor.serializeReference(targetId, expr.propertyName.name); |
| 135 return new EntityRefBuilder(reference: nameId); |
| 136 } else { |
| 137 throw new StateError('Unexpected node type: ${expr.runtimeType}'); |
| 138 } |
| 139 } |
| 140 |
| 141 @override |
| 142 EntityRefBuilder serializeType( |
| 143 DartType type, Identifier name, TypeArgumentList arguments) { |
| 144 return visitor.serializeType(name, arguments); |
| 145 } |
| 146 } |
| 147 |
| 148 /** |
| 149 * A [_Scope] represents a set of name/value pairs defined locally within a |
| 150 * limited span of a compilation unit. (Note that the spec also uses the term |
| 151 * "scope" to refer to the set of names defined at top level within a |
| 152 * compilation unit, but we do not use [_Scope] for that purpose). |
| 153 */ |
| 154 class _Scope { |
| 155 /** |
| 156 * Names defined in this scope, and their meanings. |
| 157 */ |
| 158 Map<String, _ScopedEntity> _definedNames = <String, _ScopedEntity>{}; |
| 159 |
| 160 /** |
| 161 * Look up the meaning associated with the given [name], and return it. If |
| 162 * [name] is not defined in this scope, return `null`. |
| 163 */ |
| 164 _ScopedEntity operator [](String name) => _definedNames[name]; |
| 165 |
| 166 /** |
| 167 * Let the given [name] refer to [entity] within this scope. |
| 168 */ |
| 169 void operator []=(String name, _ScopedEntity entity) { |
| 170 _definedNames[name] = entity; |
| 171 } |
| 172 } |
| 173 |
| 174 /** |
| 175 * A [_ScopedClassMember] is a [_ScopedEntity] refers to a member of a class. |
| 176 */ |
| 177 class _ScopedClassMember extends _ScopedEntity { |
| 178 /** |
| 179 * The name of the class. |
| 180 */ |
| 181 final String className; |
| 182 |
| 183 _ScopedClassMember(this.className); |
| 184 } |
| 185 |
| 186 /** |
| 187 * Base class for entities that can live inside a scope. |
| 188 */ |
| 189 abstract class _ScopedEntity {} |
| 190 |
| 191 /** |
| 192 * A [_ScopedTypeParameter] is a [_ScopedEntity] that refers to a type |
| 193 * parameter of a class, typedef, or executable. |
| 194 */ |
| 195 class _ScopedTypeParameter extends _ScopedEntity { |
| 196 /** |
| 197 * Index of the type parameter within this scope. Since summaries use De |
| 198 * Bruijn indices to refer to type parameters, which count upwards from the |
| 199 * innermost bound name, the last type parameter in the scope has an index of |
| 200 * 1, and each preceding type parameter has the next higher index. |
| 201 */ |
| 202 final int index; |
| 203 |
| 204 _ScopedTypeParameter(this.index); |
| 205 } |
| 206 |
| 207 /** |
| 208 * Visitor used to create a summary from an AST. |
| 209 */ |
| 210 class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| 211 /** |
| 212 * List of objects which should be written to [UnlinkedUnit.classes]. |
| 213 */ |
| 214 final List<UnlinkedClassBuilder> classes = <UnlinkedClassBuilder>[]; |
| 215 |
| 216 /** |
| 217 * List of objects which should be written to [UnlinkedUnit.enums]. |
| 218 */ |
| 219 final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[]; |
| 220 |
| 221 /** |
| 222 * List of objects which should be written to [UnlinkedUnit.executables], |
| 223 * [UnlinkedClass.executables] or [UnlinkedExecutable.localFunctions]. |
| 224 */ |
| 225 List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[]; |
| 226 |
| 227 /** |
| 228 * List of objects which should be written to [UnlinkedUnit.exports]. |
| 229 */ |
| 230 final List<UnlinkedExportNonPublicBuilder> exports = |
| 231 <UnlinkedExportNonPublicBuilder>[]; |
| 232 |
| 233 /** |
| 234 * List of objects which should be written to |
| 235 * [UnlinkedExecutable.localLabels]. |
| 236 */ |
| 237 List<UnlinkedLabelBuilder> labels = <UnlinkedLabelBuilder>[]; |
| 238 |
| 239 /** |
| 240 * List of objects which should be written to [UnlinkedUnit.parts]. |
| 241 */ |
| 242 final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[]; |
| 243 |
| 244 /** |
| 245 * List of objects which should be written to [UnlinkedUnit.typedefs]. |
| 246 */ |
| 247 final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[]; |
| 248 |
| 249 /** |
| 250 * List of objects which should be written to [UnlinkedUnit.variables], |
| 251 * [UnlinkedClass.fields] or [UnlinkedExecutable.localVariables]. |
| 252 */ |
| 253 List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[]; |
| 254 |
| 255 /** |
| 256 * The unlinked portion of the "imports table". This is the list of objects |
| 257 * which should be written to [UnlinkedUnit.imports]. |
| 258 */ |
| 259 final List<UnlinkedImportBuilder> unlinkedImports = <UnlinkedImportBuilder>[]; |
| 260 |
| 261 /** |
| 262 * The unlinked portion of the "references table". This is the list of |
| 263 * objects which should be written to [UnlinkedUnit.references]. |
| 264 */ |
| 265 final List<UnlinkedReferenceBuilder> unlinkedReferences = |
| 266 <UnlinkedReferenceBuilder>[new UnlinkedReferenceBuilder()]; |
| 267 |
| 268 /** |
| 269 * Map associating names used as prefixes in this compilation unit with their |
| 270 * associated indices into [UnlinkedUnit.references]. |
| 271 */ |
| 272 final Map<String, int> prefixIndices = <String, int>{}; |
| 273 |
| 274 /** |
| 275 * List of [_Scope]s currently in effect. This is used to resolve type names |
| 276 * to type parameters within classes, typedefs, and executables, as well as |
| 277 * references to class members. |
| 278 */ |
| 279 final List<_Scope> scopes = <_Scope>[]; |
| 280 |
| 281 /** |
| 282 * True if 'dart:core' has been explicitly imported. |
| 283 */ |
| 284 bool hasCoreBeenImported = false; |
| 285 |
| 286 /** |
| 287 * Names referenced by this compilation unit. Structured as a map from |
| 288 * prefix index to (map from name to reference table index), where "prefix |
| 289 * index" means the index into [UnlinkedUnit.references] of the prefix (or |
| 290 * `null` if there is no prefix), and "reference table index" means the index |
| 291 * into [UnlinkedUnit.references] for the name itself. |
| 292 */ |
| 293 final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{}; |
| 294 |
| 295 /** |
| 296 * True if the 'dart:core' library is been summarized. |
| 297 */ |
| 298 bool isCoreLibrary = false; |
| 299 |
| 300 /** |
| 301 * If the library has a library directive, the library name derived from it. |
| 302 * Otherwise `null`. |
| 303 */ |
| 304 String libraryName; |
| 305 |
| 306 /** |
| 307 * If the library has a library directive, the offset of the library name. |
| 308 * Otherwise `null`. |
| 309 */ |
| 310 int libraryNameOffset; |
| 311 |
| 312 /** |
| 313 * If the library has a library directive, the length of the library name, as |
| 314 * it appears in the source file. Otherwise `null`. |
| 315 */ |
| 316 int libraryNameLength; |
| 317 |
| 318 /** |
| 319 * If the library has a library directive, the documentation comment for it |
| 320 * (if any). Otherwise `null`. |
| 321 */ |
| 322 UnlinkedDocumentationCommentBuilder libraryDocumentationComment; |
| 323 |
| 324 /** |
| 325 * If the library has a library directive, the annotations for it (if any). |
| 326 * Otherwise `null`. |
| 327 */ |
| 328 List<UnlinkedConst> libraryAnnotations = const <UnlinkedConstBuilder>[]; |
| 329 |
| 330 /** |
| 331 * The number of slot ids which have been assigned to this compilation unit. |
| 332 */ |
| 333 int numSlots = 0; |
| 334 |
| 335 /** |
| 336 * The [Block] that is being visited now, or `null` for non-local contexts. |
| 337 */ |
| 338 Block enclosingBlock = null; |
| 339 |
| 340 /** |
| 341 * If an expression is being serialized which can contain closures, map whose |
| 342 * keys are the offsets of local function nodes representing those closures, |
| 343 * and whose values are indices of those local functions relative to their |
| 344 * siblings. |
| 345 */ |
| 346 Map<int, int> _localClosureIndexMap; |
| 347 |
| 348 /** |
| 349 * Indicates whether closure function bodies should be serialized. This flag |
| 350 * is set while visiting the bodies of initializer expressions that will be |
| 351 * needed by type inference. |
| 352 */ |
| 353 bool _serializeClosureBodyExprs = false; |
| 354 |
| 355 /** |
| 356 * If a closure function body is being serialized, the set of closure |
| 357 * parameter names which are currently in scope. Otherwise `null`. |
| 358 */ |
| 359 Set<String> _parameterNames; |
| 360 |
| 361 /** |
| 362 * Indicates whether parameters found during visitors might inherit |
| 363 * covariance. |
| 364 */ |
| 365 bool _parametersMayInheritCovariance = false; |
| 366 |
| 367 /** |
| 368 * Create a slot id for storing a propagated or inferred type or const cycle |
| 369 * info. |
| 370 */ |
| 371 int assignSlot() => ++numSlots; |
| 372 |
| 373 /** |
| 374 * Build a [_Scope] object containing the names defined within the body of a |
| 375 * class declaration. |
| 376 */ |
| 377 _Scope buildClassMemberScope( |
| 378 String className, NodeList<ClassMember> members) { |
| 379 _Scope scope = new _Scope(); |
| 380 for (ClassMember member in members) { |
| 381 if (member is MethodDeclaration) { |
| 382 if (member.isSetter || member.isOperator) { |
| 383 // We don't have to handle setters or operators because the only |
| 384 // things we look up are type names and identifiers. |
| 385 } else { |
| 386 scope[member.name.name] = new _ScopedClassMember(className); |
| 387 } |
| 388 } else if (member is FieldDeclaration) { |
| 389 for (VariableDeclaration field in member.fields.variables) { |
| 390 // A field declaration introduces two names, one with a trailing `=`. |
| 391 // We don't have to worry about the one with a trailing `=` because |
| 392 // the only things we look up are type names and identifiers. |
| 393 scope[field.name.name] = new _ScopedClassMember(className); |
| 394 } |
| 395 } |
| 396 } |
| 397 return scope; |
| 398 } |
| 399 |
| 400 /** |
| 401 * Serialize the given list of [annotations]. If there are no annotations, |
| 402 * the empty list is returned. |
| 403 */ |
| 404 List<UnlinkedConstBuilder> serializeAnnotations( |
| 405 NodeList<Annotation> annotations) { |
| 406 if (annotations == null || annotations.isEmpty) { |
| 407 return const <UnlinkedConstBuilder>[]; |
| 408 } |
| 409 return annotations.map((Annotation a) { |
| 410 // Closures can't appear inside annotations, so we don't need a |
| 411 // localClosureIndexMap. |
| 412 Map<int, int> localClosureIndexMap = null; |
| 413 _ConstExprSerializer serializer = |
| 414 new _ConstExprSerializer(this, localClosureIndexMap, null); |
| 415 serializer.serializeAnnotation(a); |
| 416 return serializer.toBuilder(); |
| 417 }).toList(); |
| 418 } |
| 419 |
| 420 /** |
| 421 * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass] |
| 422 * and store the result in [classes]. |
| 423 */ |
| 424 void serializeClass( |
| 425 AstNode node, |
| 426 Token abstractKeyword, |
| 427 String name, |
| 428 int nameOffset, |
| 429 TypeParameterList typeParameters, |
| 430 TypeName superclass, |
| 431 WithClause withClause, |
| 432 ImplementsClause implementsClause, |
| 433 NodeList<ClassMember> members, |
| 434 bool isMixinApplication, |
| 435 Comment documentationComment, |
| 436 NodeList<Annotation> annotations) { |
| 437 int oldScopesLength = scopes.length; |
| 438 List<UnlinkedExecutableBuilder> oldExecutables = executables; |
| 439 executables = <UnlinkedExecutableBuilder>[]; |
| 440 List<UnlinkedVariableBuilder> oldVariables = variables; |
| 441 variables = <UnlinkedVariableBuilder>[]; |
| 442 _TypeParameterScope typeParameterScope = new _TypeParameterScope(); |
| 443 scopes.add(typeParameterScope); |
| 444 UnlinkedClassBuilder b = new UnlinkedClassBuilder(); |
| 445 b.name = name; |
| 446 b.nameOffset = nameOffset; |
| 447 b.isMixinApplication = isMixinApplication; |
| 448 b.typeParameters = |
| 449 serializeTypeParameters(typeParameters, typeParameterScope); |
| 450 if (superclass != null) { |
| 451 b.supertype = serializeTypeName(superclass); |
| 452 } else { |
| 453 b.hasNoSupertype = isCoreLibrary && name == 'Object'; |
| 454 } |
| 455 if (withClause != null) { |
| 456 b.mixins = withClause.mixinTypes.map(serializeTypeName).toList(); |
| 457 } |
| 458 if (implementsClause != null) { |
| 459 b.interfaces = |
| 460 implementsClause.interfaces.map(serializeTypeName).toList(); |
| 461 } |
| 462 if (members != null) { |
| 463 scopes.add(buildClassMemberScope(name, members)); |
| 464 for (ClassMember member in members) { |
| 465 member.accept(this); |
| 466 } |
| 467 scopes.removeLast(); |
| 468 } |
| 469 b.executables = executables; |
| 470 b.fields = variables; |
| 471 b.isAbstract = abstractKeyword != null; |
| 472 b.documentationComment = serializeDocumentation(documentationComment); |
| 473 b.annotations = serializeAnnotations(annotations); |
| 474 b.codeRange = serializeCodeRange(node); |
| 475 classes.add(b); |
| 476 scopes.removeLast(); |
| 477 assert(scopes.length == oldScopesLength); |
| 478 executables = oldExecutables; |
| 479 variables = oldVariables; |
| 480 } |
| 481 |
| 482 /** |
| 483 * Create a [CodeRangeBuilder] for the given [node]. |
| 484 */ |
| 485 CodeRangeBuilder serializeCodeRange(AstNode node) { |
| 486 return new CodeRangeBuilder(offset: node.offset, length: node.length); |
| 487 } |
| 488 |
| 489 /** |
| 490 * Serialize a [Combinator] into an [UnlinkedCombinator]. |
| 491 */ |
| 492 UnlinkedCombinatorBuilder serializeCombinator(Combinator combinator) { |
| 493 UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder(); |
| 494 if (combinator is ShowCombinator) { |
| 495 b.shows = |
| 496 combinator.shownNames.map((SimpleIdentifier id) => id.name).toList(); |
| 497 b.offset = combinator.offset; |
| 498 b.end = combinator.end; |
| 499 } else if (combinator is HideCombinator) { |
| 500 b.hides = |
| 501 combinator.hiddenNames.map((SimpleIdentifier id) => id.name).toList(); |
| 502 } else { |
| 503 throw new StateError( |
| 504 'Unexpected combinator type: ${combinator.runtimeType}'); |
| 505 } |
| 506 return b; |
| 507 } |
| 508 |
| 509 /** |
| 510 * Main entry point for serializing an AST. |
| 511 */ |
| 512 UnlinkedUnitBuilder serializeCompilationUnit( |
| 513 CompilationUnit compilationUnit) { |
| 514 compilationUnit.directives.accept(this); |
| 515 if (!hasCoreBeenImported) { |
| 516 unlinkedImports.add(new UnlinkedImportBuilder(isImplicit: true)); |
| 517 } |
| 518 compilationUnit.declarations.accept(this); |
| 519 UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(); |
| 520 b.lineStarts = compilationUnit.lineInfo?.lineStarts; |
| 521 b.libraryName = libraryName; |
| 522 b.libraryNameOffset = libraryNameOffset; |
| 523 b.libraryNameLength = libraryNameLength; |
| 524 b.libraryDocumentationComment = libraryDocumentationComment; |
| 525 b.libraryAnnotations = libraryAnnotations; |
| 526 b.codeRange = serializeCodeRange(compilationUnit); |
| 527 b.classes = classes; |
| 528 b.enums = enums; |
| 529 b.executables = executables; |
| 530 b.exports = exports; |
| 531 b.imports = unlinkedImports; |
| 532 b.parts = parts; |
| 533 b.references = unlinkedReferences; |
| 534 b.typedefs = typedefs; |
| 535 b.variables = variables; |
| 536 b.publicNamespace = computePublicNamespace(compilationUnit); |
| 537 return b; |
| 538 } |
| 539 |
| 540 /** |
| 541 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. |
| 542 */ |
| 543 UnlinkedConstBuilder serializeConstExpr( |
| 544 Map<int, int> localClosureIndexMap, Expression expression, |
| 545 [Set<String> parameterNames]) { |
| 546 _ConstExprSerializer serializer = |
| 547 new _ConstExprSerializer(this, localClosureIndexMap, parameterNames); |
| 548 serializer.serialize(expression); |
| 549 return serializer.toBuilder(); |
| 550 } |
| 551 |
| 552 /** |
| 553 * Serialize the given [declaredIdentifier] into [UnlinkedVariable], and |
| 554 * store it in [variables]. |
| 555 */ |
| 556 void serializeDeclaredIdentifier( |
| 557 AstNode scopeNode, |
| 558 Comment documentationComment, |
| 559 NodeList<Annotation> annotations, |
| 560 bool isFinal, |
| 561 bool isConst, |
| 562 TypeName type, |
| 563 bool assignPropagatedTypeSlot, |
| 564 SimpleIdentifier declaredIdentifier) { |
| 565 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); |
| 566 b.isFinal = isFinal; |
| 567 b.isConst = isConst; |
| 568 b.name = declaredIdentifier.name; |
| 569 b.nameOffset = declaredIdentifier.offset; |
| 570 b.type = serializeTypeName(type); |
| 571 b.documentationComment = serializeDocumentation(documentationComment); |
| 572 b.annotations = serializeAnnotations(annotations); |
| 573 b.codeRange = serializeCodeRange(declaredIdentifier); |
| 574 if (assignPropagatedTypeSlot) { |
| 575 b.propagatedTypeSlot = assignSlot(); |
| 576 } |
| 577 b.visibleOffset = scopeNode?.offset; |
| 578 b.visibleLength = scopeNode?.length; |
| 579 this.variables.add(b); |
| 580 } |
| 581 |
| 582 /** |
| 583 * Serialize a [Comment] node into an [UnlinkedDocumentationComment] object. |
| 584 */ |
| 585 UnlinkedDocumentationCommentBuilder serializeDocumentation( |
| 586 Comment documentationComment) { |
| 587 if (documentationComment == null) { |
| 588 return null; |
| 589 } |
| 590 String text = documentationComment.tokens |
| 591 .map((Token t) => t.toString()) |
| 592 .join() |
| 593 .replaceAll('\r\n', '\n'); |
| 594 return new UnlinkedDocumentationCommentBuilder(text: text); |
| 595 } |
| 596 |
| 597 /** |
| 598 * Serialize a [FunctionDeclaration] or [MethodDeclaration] into an |
| 599 * [UnlinkedExecutable]. |
| 600 * |
| 601 * If [serializeBodyExpr] is `true`, then the function definition is stored |
| 602 * in [UnlinkedExecutableBuilder.bodyExpr]. |
| 603 */ |
| 604 UnlinkedExecutableBuilder serializeExecutable( |
| 605 AstNode node, |
| 606 String name, |
| 607 int nameOffset, |
| 608 bool isGetter, |
| 609 bool isSetter, |
| 610 TypeName returnType, |
| 611 FormalParameterList formalParameters, |
| 612 FunctionBody body, |
| 613 bool isTopLevel, |
| 614 bool isDeclaredStatic, |
| 615 Comment documentationComment, |
| 616 NodeList<Annotation> annotations, |
| 617 TypeParameterList typeParameters, |
| 618 bool isExternal, |
| 619 bool serializeBodyExpr) { |
| 620 int oldScopesLength = scopes.length; |
| 621 _TypeParameterScope typeParameterScope = new _TypeParameterScope(); |
| 622 scopes.add(typeParameterScope); |
| 623 UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder(); |
| 624 String nameString = name; |
| 625 if (isGetter) { |
| 626 b.kind = UnlinkedExecutableKind.getter; |
| 627 } else if (isSetter) { |
| 628 b.kind = UnlinkedExecutableKind.setter; |
| 629 nameString = '$nameString='; |
| 630 } else { |
| 631 b.kind = UnlinkedExecutableKind.functionOrMethod; |
| 632 } |
| 633 b.isExternal = isExternal; |
| 634 b.isAbstract = !isExternal && body is EmptyFunctionBody; |
| 635 b.isAsynchronous = body.isAsynchronous; |
| 636 b.isGenerator = body.isGenerator; |
| 637 b.name = nameString; |
| 638 b.nameOffset = nameOffset; |
| 639 b.typeParameters = |
| 640 serializeTypeParameters(typeParameters, typeParameterScope); |
| 641 if (!isTopLevel) { |
| 642 b.isStatic = isDeclaredStatic; |
| 643 } |
| 644 b.returnType = serializeTypeName(returnType); |
| 645 bool isSemanticallyStatic = isTopLevel || isDeclaredStatic; |
| 646 if (formalParameters != null) { |
| 647 bool oldMayInheritCovariance = _parametersMayInheritCovariance; |
| 648 _parametersMayInheritCovariance = !isTopLevel && !isDeclaredStatic; |
| 649 b.parameters = formalParameters.parameters |
| 650 .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder) |
| 651 .toList(); |
| 652 _parametersMayInheritCovariance = oldMayInheritCovariance; |
| 653 if (!isSemanticallyStatic) { |
| 654 for (int i = 0; i < formalParameters.parameters.length; i++) { |
| 655 if (!b.parameters[i].isFunctionTyped && |
| 656 b.parameters[i].type == null) { |
| 657 b.parameters[i].inferredTypeSlot = assignSlot(); |
| 658 } |
| 659 } |
| 660 } |
| 661 } |
| 662 b.documentationComment = serializeDocumentation(documentationComment); |
| 663 b.annotations = serializeAnnotations(annotations); |
| 664 b.codeRange = serializeCodeRange(node); |
| 665 if (returnType == null && !isSemanticallyStatic) { |
| 666 b.inferredReturnTypeSlot = assignSlot(); |
| 667 } |
| 668 b.visibleOffset = enclosingBlock?.offset; |
| 669 b.visibleLength = enclosingBlock?.length; |
| 670 Set<String> oldParameterNames = _parameterNames; |
| 671 if (formalParameters != null && formalParameters.parameters.isNotEmpty) { |
| 672 _parameterNames = |
| 673 _parameterNames == null ? new Set<String>() : _parameterNames.toSet(); |
| 674 _parameterNames.addAll(formalParameters.parameters |
| 675 .map((FormalParameter p) => p.identifier.name)); |
| 676 } |
| 677 serializeFunctionBody(b, null, body, serializeBodyExpr); |
| 678 _parameterNames = oldParameterNames; |
| 679 scopes.removeLast(); |
| 680 assert(scopes.length == oldScopesLength); |
| 681 return b; |
| 682 } |
| 683 |
| 684 /** |
| 685 * Record local functions and variables into the given executable. The given |
| 686 * [body] is usually an actual [FunctionBody], but may be an [Expression] |
| 687 * when we process a synthetic variable initializer function. |
| 688 * |
| 689 * If [initializers] is non-`null`, closures occurring inside the initializers |
| 690 * are serialized first. |
| 691 * |
| 692 * If [serializeBodyExpr] is `true`, then the function definition is stored |
| 693 * in [UnlinkedExecutableBuilder.bodyExpr], and closures occurring inside |
| 694 * [initializers] and [body] have their function bodies serialized as well. |
| 695 * |
| 696 * The return value is a map whose keys are the offsets of local function |
| 697 * nodes representing closures inside [initializers] and [body], and whose |
| 698 * values are the indices of those local functions relative to their siblings. |
| 699 */ |
| 700 Map<int, int> serializeFunctionBody( |
| 701 UnlinkedExecutableBuilder b, |
| 702 List<ConstructorInitializer> initializers, |
| 703 AstNode body, |
| 704 bool serializeBodyExpr) { |
| 705 if (body is BlockFunctionBody || body is ExpressionFunctionBody) { |
| 706 for (UnlinkedParamBuilder parameter in b.parameters) { |
| 707 parameter.visibleOffset = body.offset; |
| 708 parameter.visibleLength = body.length; |
| 709 } |
| 710 } |
| 711 List<UnlinkedExecutableBuilder> oldExecutables = executables; |
| 712 List<UnlinkedLabelBuilder> oldLabels = labels; |
| 713 List<UnlinkedVariableBuilder> oldVariables = variables; |
| 714 Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap; |
| 715 bool oldSerializeClosureBodyExprs = _serializeClosureBodyExprs; |
| 716 executables = <UnlinkedExecutableBuilder>[]; |
| 717 labels = <UnlinkedLabelBuilder>[]; |
| 718 variables = <UnlinkedVariableBuilder>[]; |
| 719 _localClosureIndexMap = <int, int>{}; |
| 720 _serializeClosureBodyExprs = serializeBodyExpr; |
| 721 if (initializers != null) { |
| 722 for (ConstructorInitializer initializer in initializers) { |
| 723 initializer.accept(this); |
| 724 } |
| 725 } |
| 726 body.accept(this); |
| 727 if (serializeBodyExpr) { |
| 728 if (body is Expression) { |
| 729 b.bodyExpr = |
| 730 serializeConstExpr(_localClosureIndexMap, body, _parameterNames); |
| 731 } else if (body is ExpressionFunctionBody) { |
| 732 b.bodyExpr = serializeConstExpr( |
| 733 _localClosureIndexMap, body.expression, _parameterNames); |
| 734 } else { |
| 735 // TODO(paulberry): serialize other types of function bodies. |
| 736 } |
| 737 } |
| 738 b.localFunctions = executables; |
| 739 b.localLabels = labels; |
| 740 b.localVariables = variables; |
| 741 Map<int, int> localClosureIndexMap = _localClosureIndexMap; |
| 742 executables = oldExecutables; |
| 743 labels = oldLabels; |
| 744 variables = oldVariables; |
| 745 _localClosureIndexMap = oldLocalClosureIndexMap; |
| 746 _serializeClosureBodyExprs = oldSerializeClosureBodyExprs; |
| 747 return localClosureIndexMap; |
| 748 } |
| 749 |
| 750 /** |
| 751 * Serialize the return type and parameters of a function-typed formal |
| 752 * parameter and store them in [b]. |
| 753 */ |
| 754 void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b, |
| 755 TypeName returnType, FormalParameterList parameters) { |
| 756 EntityRefBuilder serializedReturnType = serializeTypeName(returnType); |
| 757 if (serializedReturnType != null) { |
| 758 b.type = serializedReturnType; |
| 759 } |
| 760 bool oldMayInheritCovariance = _parametersMayInheritCovariance; |
| 761 _parametersMayInheritCovariance = false; |
| 762 b.parameters = parameters.parameters |
| 763 .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder) |
| 764 .toList(); |
| 765 _parametersMayInheritCovariance = oldMayInheritCovariance; |
| 766 } |
| 767 |
| 768 /** |
| 769 * If the given [expression] is not `null`, serialize it as an |
| 770 * [UnlinkedExecutableBuilder], otherwise return `null`. |
| 771 * |
| 772 * If [serializeBodyExpr] is `true`, then the initializer expression is stored |
| 773 * in [UnlinkedExecutableBuilder.bodyExpr]. |
| 774 */ |
| 775 UnlinkedExecutableBuilder serializeInitializerFunction( |
| 776 Expression expression, bool serializeBodyExpr) { |
| 777 if (expression == null) { |
| 778 return null; |
| 779 } |
| 780 UnlinkedExecutableBuilder initializer = |
| 781 new UnlinkedExecutableBuilder(nameOffset: expression.offset); |
| 782 serializeFunctionBody(initializer, null, expression, serializeBodyExpr); |
| 783 initializer.inferredReturnTypeSlot = assignSlot(); |
| 784 return initializer; |
| 785 } |
| 786 |
| 787 /** |
| 788 * Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or |
| 789 * [SimpleFormalParameter] into an [UnlinkedParam]. |
| 790 */ |
| 791 UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) { |
| 792 UnlinkedParamBuilder b = new UnlinkedParamBuilder(); |
| 793 b.name = node.identifier.name; |
| 794 b.nameOffset = node.identifier.offset; |
| 795 b.annotations = serializeAnnotations(node.metadata); |
| 796 b.codeRange = serializeCodeRange(node); |
| 797 if (_parametersMayInheritCovariance) { |
| 798 b.inheritsCovariantSlot = assignSlot(); |
| 799 } |
| 800 switch (node.kind) { |
| 801 case ParameterKind.REQUIRED: |
| 802 b.kind = UnlinkedParamKind.required; |
| 803 break; |
| 804 case ParameterKind.POSITIONAL: |
| 805 b.kind = UnlinkedParamKind.positional; |
| 806 break; |
| 807 case ParameterKind.NAMED: |
| 808 b.kind = UnlinkedParamKind.named; |
| 809 break; |
| 810 default: |
| 811 throw new StateError('Unexpected parameter kind: ${node.kind}'); |
| 812 } |
| 813 return b; |
| 814 } |
| 815 |
| 816 /** |
| 817 * Serialize a reference to a top level name declared elsewhere, by adding an |
| 818 * entry to the references table if necessary. If [prefixIndex] is not null, |
| 819 * the reference is associated with the prefix having the given index in the |
| 820 * references table. |
| 821 */ |
| 822 int serializeReference(int prefixIndex, String name) => nameToReference |
| 823 .putIfAbsent(prefixIndex, () => <String, int>{}) |
| 824 .putIfAbsent(name, () { |
| 825 int index = unlinkedReferences.length; |
| 826 unlinkedReferences.add(new UnlinkedReferenceBuilder( |
| 827 prefixReference: prefixIndex, name: name)); |
| 828 return index; |
| 829 }); |
| 830 |
| 831 /** |
| 832 * Serialize a reference to a name declared either at top level or in a |
| 833 * nested scope. |
| 834 * |
| 835 * If [allowTypeParameter] is `true`, then references to type |
| 836 * parameters are allowed, and are returned as negative numbers. |
| 837 */ |
| 838 int serializeSimpleReference(String name, {bool allowTypeParameter: false}) { |
| 839 int indexOffset = 0; |
| 840 for (int i = scopes.length - 1; i >= 0; i--) { |
| 841 _Scope scope = scopes[i]; |
| 842 _ScopedEntity entity = scope[name]; |
| 843 if (entity != null) { |
| 844 if (entity is _ScopedClassMember) { |
| 845 return serializeReference( |
| 846 serializeReference(null, entity.className), name); |
| 847 } else if (allowTypeParameter && entity is _ScopedTypeParameter) { |
| 848 int paramReference = indexOffset + entity.index; |
| 849 return -paramReference; |
| 850 } else { |
| 851 // Invalid reference to a type parameter. Should never happen in |
| 852 // legal Dart code. |
| 853 // TODO(paulberry): could this exception ever be uncaught in illegal |
| 854 // code? |
| 855 throw new StateError('Invalid identifier reference'); |
| 856 } |
| 857 } |
| 858 if (scope is _TypeParameterScope) { |
| 859 indexOffset += scope.length; |
| 860 } |
| 861 } |
| 862 return serializeReference(null, name); |
| 863 } |
| 864 |
| 865 /** |
| 866 * Serialize a type name (which might be defined in a nested scope, at top |
| 867 * level within this library, or at top level within an imported library) to |
| 868 * a [EntityRef]. Note that this method does the right thing if the |
| 869 * name doesn't refer to an entity other than a type (e.g. a class member). |
| 870 */ |
| 871 EntityRefBuilder serializeType( |
| 872 Identifier identifier, TypeArgumentList typeArguments) { |
| 873 if (identifier == null) { |
| 874 return null; |
| 875 } else { |
| 876 EntityRefBuilder b = new EntityRefBuilder(); |
| 877 if (identifier is SimpleIdentifier) { |
| 878 String name = identifier.name; |
| 879 int indexOffset = 0; |
| 880 for (int i = scopes.length - 1; i >= 0; i--) { |
| 881 _Scope scope = scopes[i]; |
| 882 _ScopedEntity entity = scope[name]; |
| 883 if (entity != null) { |
| 884 if (entity is _ScopedTypeParameter) { |
| 885 b.paramReference = indexOffset + entity.index; |
| 886 return b; |
| 887 } else { |
| 888 // None of the other things that can be declared in local scopes |
| 889 // are types, so this is an error and should be treated as a |
| 890 // reference to `dynamic`. |
| 891 b.reference = serializeReference(null, 'dynamic'); |
| 892 return b; |
| 893 } |
| 894 } |
| 895 if (scope is _TypeParameterScope) { |
| 896 indexOffset += scope.length; |
| 897 } |
| 898 } |
| 899 b.reference = serializeReference(null, name); |
| 900 } else if (identifier is PrefixedIdentifier) { |
| 901 int prefixIndex = prefixIndices.putIfAbsent(identifier.prefix.name, |
| 902 () => serializeSimpleReference(identifier.prefix.name)); |
| 903 b.reference = |
| 904 serializeReference(prefixIndex, identifier.identifier.name); |
| 905 } else { |
| 906 throw new StateError( |
| 907 'Unexpected identifier type: ${identifier.runtimeType}'); |
| 908 } |
| 909 if (typeArguments != null) { |
| 910 b.typeArguments = |
| 911 typeArguments.arguments.map(serializeTypeName).toList(); |
| 912 } |
| 913 return b; |
| 914 } |
| 915 } |
| 916 |
| 917 /** |
| 918 * Serialize a type name (which might be defined in a nested scope, at top |
| 919 * level within this library, or at top level within an imported library) to |
| 920 * a [EntityRef]. Note that this method does the right thing if the |
| 921 * name doesn't refer to an entity other than a type (e.g. a class member). |
| 922 */ |
| 923 EntityRefBuilder serializeTypeName(TypeName node) { |
| 924 return serializeType(node?.name, node?.typeArguments); |
| 925 } |
| 926 |
| 927 /** |
| 928 * Serialize the given [typeParameters] into a list of [UnlinkedTypeParam]s, |
| 929 * and also store them in [typeParameterScope]. |
| 930 */ |
| 931 List<UnlinkedTypeParamBuilder> serializeTypeParameters( |
| 932 TypeParameterList typeParameters, |
| 933 _TypeParameterScope typeParameterScope) { |
| 934 if (typeParameters != null) { |
| 935 for (int i = 0; i < typeParameters.typeParameters.length; i++) { |
| 936 TypeParameter typeParameter = typeParameters.typeParameters[i]; |
| 937 typeParameterScope[typeParameter.name.name] = |
| 938 new _ScopedTypeParameter(typeParameters.typeParameters.length - i); |
| 939 } |
| 940 return typeParameters.typeParameters.map(visitTypeParameter).toList(); |
| 941 } |
| 942 return const <UnlinkedTypeParamBuilder>[]; |
| 943 } |
| 944 |
| 945 /** |
| 946 * Serialize the given [variables] into [UnlinkedVariable]s, and store them |
| 947 * in [this.variables]. |
| 948 */ |
| 949 void serializeVariables( |
| 950 AstNode scopeNode, |
| 951 VariableDeclarationList variables, |
| 952 bool isDeclaredStatic, |
| 953 Comment documentationComment, |
| 954 NodeList<Annotation> annotations, |
| 955 bool isField) { |
| 956 for (VariableDeclaration variable in variables.variables) { |
| 957 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); |
| 958 b.isFinal = variables.isFinal; |
| 959 b.isConst = variables.isConst; |
| 960 b.isStatic = isDeclaredStatic; |
| 961 b.name = variable.name.name; |
| 962 b.nameOffset = variable.name.offset; |
| 963 b.type = serializeTypeName(variables.type); |
| 964 b.documentationComment = serializeDocumentation(documentationComment); |
| 965 b.annotations = serializeAnnotations(annotations); |
| 966 b.codeRange = serializeCodeRange(variables.parent); |
| 967 bool serializeBodyExpr = variable.isConst || |
| 968 variable.isFinal && isField && !isDeclaredStatic || |
| 969 variables.type == null; |
| 970 b.initializer = |
| 971 serializeInitializerFunction(variable.initializer, serializeBodyExpr); |
| 972 if (variable.initializer != null && |
| 973 (variables.isFinal || variables.isConst)) { |
| 974 b.propagatedTypeSlot = assignSlot(); |
| 975 } |
| 976 bool isSemanticallyStatic = !isField || isDeclaredStatic; |
| 977 if (variables.type == null && |
| 978 (variable.initializer != null || !isSemanticallyStatic)) { |
| 979 b.inferredTypeSlot = assignSlot(); |
| 980 } |
| 981 b.visibleOffset = scopeNode?.offset; |
| 982 b.visibleLength = scopeNode?.length; |
| 983 this.variables.add(b); |
| 984 } |
| 985 } |
| 986 |
| 987 @override |
| 988 void visitBlock(Block node) { |
| 989 Block oldBlock = enclosingBlock; |
| 990 enclosingBlock = node; |
| 991 super.visitBlock(node); |
| 992 enclosingBlock = oldBlock; |
| 993 } |
| 994 |
| 995 @override |
| 996 void visitCatchClause(CatchClause node) { |
| 997 SimpleIdentifier exception = node.exceptionParameter; |
| 998 SimpleIdentifier st = node.stackTraceParameter; |
| 999 if (exception != null) { |
| 1000 serializeDeclaredIdentifier( |
| 1001 node, null, null, false, false, node.exceptionType, false, exception); |
| 1002 } |
| 1003 if (st != null) { |
| 1004 serializeDeclaredIdentifier( |
| 1005 node, null, null, false, false, null, false, st); |
| 1006 } |
| 1007 super.visitCatchClause(node); |
| 1008 } |
| 1009 |
| 1010 @override |
| 1011 void visitClassDeclaration(ClassDeclaration node) { |
| 1012 TypeName superclass = |
| 1013 node.extendsClause == null ? null : node.extendsClause.superclass; |
| 1014 serializeClass( |
| 1015 node, |
| 1016 node.abstractKeyword, |
| 1017 node.name.name, |
| 1018 node.name.offset, |
| 1019 node.typeParameters, |
| 1020 superclass, |
| 1021 node.withClause, |
| 1022 node.implementsClause, |
| 1023 node.members, |
| 1024 false, |
| 1025 node.documentationComment, |
| 1026 node.metadata); |
| 1027 } |
| 1028 |
| 1029 @override |
| 1030 void visitClassTypeAlias(ClassTypeAlias node) { |
| 1031 serializeClass( |
| 1032 node, |
| 1033 node.abstractKeyword, |
| 1034 node.name.name, |
| 1035 node.name.offset, |
| 1036 node.typeParameters, |
| 1037 node.superclass, |
| 1038 node.withClause, |
| 1039 node.implementsClause, |
| 1040 null, |
| 1041 true, |
| 1042 node.documentationComment, |
| 1043 node.metadata); |
| 1044 } |
| 1045 |
| 1046 @override |
| 1047 void visitConstructorDeclaration(ConstructorDeclaration node) { |
| 1048 UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder(); |
| 1049 if (node.name != null) { |
| 1050 b.name = node.name.name; |
| 1051 b.nameOffset = node.name.offset; |
| 1052 b.periodOffset = node.period.offset; |
| 1053 b.nameEnd = node.name.end; |
| 1054 } else { |
| 1055 b.nameOffset = node.returnType.offset; |
| 1056 } |
| 1057 b.parameters = node.parameters.parameters |
| 1058 .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder) |
| 1059 .toList(); |
| 1060 b.kind = UnlinkedExecutableKind.constructor; |
| 1061 if (node.factoryKeyword != null) { |
| 1062 b.isFactory = true; |
| 1063 if (node.redirectedConstructor != null) { |
| 1064 b.isRedirectedConstructor = true; |
| 1065 TypeName typeName = node.redirectedConstructor.type; |
| 1066 // Closures can't appear inside factory constructor redirections, so we |
| 1067 // don't need a localClosureIndexMap. |
| 1068 Map<int, int> localClosureIndexMap = null; |
| 1069 b.redirectedConstructor = |
| 1070 new _ConstExprSerializer(this, localClosureIndexMap, null) |
| 1071 .serializeConstructorRef(null, typeName.name, |
| 1072 typeName.typeArguments, node.redirectedConstructor.name); |
| 1073 } |
| 1074 } else { |
| 1075 for (ConstructorInitializer initializer in node.initializers) { |
| 1076 if (initializer is RedirectingConstructorInvocation) { |
| 1077 b.isRedirectedConstructor = true; |
| 1078 b.redirectedConstructorName = initializer.constructorName?.name; |
| 1079 } |
| 1080 } |
| 1081 } |
| 1082 if (node.constKeyword != null) { |
| 1083 b.isConst = true; |
| 1084 b.constCycleSlot = assignSlot(); |
| 1085 } |
| 1086 b.isExternal = node.externalKeyword != null; |
| 1087 b.documentationComment = serializeDocumentation(node.documentationComment); |
| 1088 b.annotations = serializeAnnotations(node.metadata); |
| 1089 b.codeRange = serializeCodeRange(node); |
| 1090 Map<int, int> localClosureIndexMap = serializeFunctionBody( |
| 1091 b, node.initializers, node.body, node.constKeyword != null); |
| 1092 if (node.constKeyword != null) { |
| 1093 Set<String> constructorParameterNames = |
| 1094 node.parameters.parameters.map((p) => p.identifier.name).toSet(); |
| 1095 b.constantInitializers = node.initializers |
| 1096 .map((ConstructorInitializer initializer) => |
| 1097 serializeConstructorInitializer(initializer, (Expression expr) { |
| 1098 return serializeConstExpr( |
| 1099 localClosureIndexMap, expr, constructorParameterNames); |
| 1100 })) |
| 1101 .toList(); |
| 1102 } |
| 1103 executables.add(b); |
| 1104 } |
| 1105 |
| 1106 @override |
| 1107 UnlinkedParamBuilder visitDefaultFormalParameter( |
| 1108 DefaultFormalParameter node) { |
| 1109 UnlinkedParamBuilder b = |
| 1110 node.parameter.accept(this) as UnlinkedParamBuilder; |
| 1111 b.initializer = serializeInitializerFunction(node.defaultValue, true); |
| 1112 if (node.defaultValue != null) { |
| 1113 b.defaultValueCode = node.defaultValue.toSource(); |
| 1114 } |
| 1115 b.codeRange = serializeCodeRange(node); |
| 1116 return b; |
| 1117 } |
| 1118 |
| 1119 @override |
| 1120 void visitEnumDeclaration(EnumDeclaration node) { |
| 1121 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(); |
| 1122 b.name = node.name.name; |
| 1123 b.nameOffset = node.name.offset; |
| 1124 b.values = node.constants |
| 1125 .map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder( |
| 1126 documentationComment: |
| 1127 serializeDocumentation(value.documentationComment), |
| 1128 name: value.name.name, |
| 1129 nameOffset: value.name.offset)) |
| 1130 .toList(); |
| 1131 b.documentationComment = serializeDocumentation(node.documentationComment); |
| 1132 b.annotations = serializeAnnotations(node.metadata); |
| 1133 b.codeRange = serializeCodeRange(node); |
| 1134 enums.add(b); |
| 1135 } |
| 1136 |
| 1137 @override |
| 1138 void visitExportDirective(ExportDirective node) { |
| 1139 UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder( |
| 1140 uriOffset: node.uri.offset, uriEnd: node.uri.end, offset: node.offset); |
| 1141 b.annotations = serializeAnnotations(node.metadata); |
| 1142 exports.add(b); |
| 1143 } |
| 1144 |
| 1145 @override |
| 1146 void visitFieldDeclaration(FieldDeclaration node) { |
| 1147 serializeVariables(null, node.fields, node.staticKeyword != null, |
| 1148 node.documentationComment, node.metadata, true); |
| 1149 } |
| 1150 |
| 1151 @override |
| 1152 UnlinkedParamBuilder visitFieldFormalParameter(FieldFormalParameter node) { |
| 1153 UnlinkedParamBuilder b = serializeParameter(node); |
| 1154 b.isInitializingFormal = true; |
| 1155 if (node.type != null || node.parameters != null) { |
| 1156 b.isFunctionTyped = node.parameters != null; |
| 1157 if (node.parameters != null) { |
| 1158 serializeFunctionTypedParameterDetails(b, node.type, node.parameters); |
| 1159 } else { |
| 1160 b.type = serializeTypeName(node.type); |
| 1161 } |
| 1162 } |
| 1163 return b; |
| 1164 } |
| 1165 |
| 1166 @override |
| 1167 void visitForEachStatement(ForEachStatement node) { |
| 1168 DeclaredIdentifier loopVariable = node.loopVariable; |
| 1169 if (loopVariable != null) { |
| 1170 serializeDeclaredIdentifier( |
| 1171 node, |
| 1172 loopVariable.documentationComment, |
| 1173 loopVariable.metadata, |
| 1174 loopVariable.isFinal, |
| 1175 loopVariable.isConst, |
| 1176 loopVariable.type, |
| 1177 true, |
| 1178 loopVariable.identifier); |
| 1179 } |
| 1180 super.visitForEachStatement(node); |
| 1181 } |
| 1182 |
| 1183 @override |
| 1184 void visitForStatement(ForStatement node) { |
| 1185 VariableDeclarationList declaredVariables = node.variables; |
| 1186 if (declaredVariables != null) { |
| 1187 serializeVariables(node, declaredVariables, false, null, null, false); |
| 1188 } |
| 1189 super.visitForStatement(node); |
| 1190 } |
| 1191 |
| 1192 @override |
| 1193 void visitFunctionDeclaration(FunctionDeclaration node) { |
| 1194 executables.add(serializeExecutable( |
| 1195 node, |
| 1196 node.name.name, |
| 1197 node.name.offset, |
| 1198 node.isGetter, |
| 1199 node.isSetter, |
| 1200 node.returnType, |
| 1201 node.functionExpression.parameters, |
| 1202 node.functionExpression.body, |
| 1203 true, |
| 1204 false, |
| 1205 node.documentationComment, |
| 1206 node.metadata, |
| 1207 node.functionExpression.typeParameters, |
| 1208 node.externalKeyword != null, |
| 1209 false)); |
| 1210 } |
| 1211 |
| 1212 @override |
| 1213 void visitFunctionExpression(FunctionExpression node) { |
| 1214 if (node.parent is! FunctionDeclaration) { |
| 1215 if (_localClosureIndexMap != null) { |
| 1216 _localClosureIndexMap[node.offset] = executables.length; |
| 1217 } |
| 1218 executables.add(serializeExecutable( |
| 1219 node, |
| 1220 null, |
| 1221 node.offset, |
| 1222 false, |
| 1223 false, |
| 1224 null, |
| 1225 node.parameters, |
| 1226 node.body, |
| 1227 false, |
| 1228 false, |
| 1229 null, |
| 1230 null, |
| 1231 node.typeParameters, |
| 1232 false, |
| 1233 _serializeClosureBodyExprs)); |
| 1234 } |
| 1235 } |
| 1236 |
| 1237 @override |
| 1238 void visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 1239 int oldScopesLength = scopes.length; |
| 1240 _TypeParameterScope typeParameterScope = new _TypeParameterScope(); |
| 1241 scopes.add(typeParameterScope); |
| 1242 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder(); |
| 1243 b.name = node.name.name; |
| 1244 b.nameOffset = node.name.offset; |
| 1245 b.typeParameters = |
| 1246 serializeTypeParameters(node.typeParameters, typeParameterScope); |
| 1247 EntityRefBuilder serializedReturnType = serializeTypeName(node.returnType); |
| 1248 if (serializedReturnType != null) { |
| 1249 b.returnType = serializedReturnType; |
| 1250 } |
| 1251 b.parameters = node.parameters.parameters |
| 1252 .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder) |
| 1253 .toList(); |
| 1254 b.documentationComment = serializeDocumentation(node.documentationComment); |
| 1255 b.annotations = serializeAnnotations(node.metadata); |
| 1256 b.codeRange = serializeCodeRange(node); |
| 1257 typedefs.add(b); |
| 1258 scopes.removeLast(); |
| 1259 assert(scopes.length == oldScopesLength); |
| 1260 } |
| 1261 |
| 1262 @override |
| 1263 UnlinkedParamBuilder visitFunctionTypedFormalParameter( |
| 1264 FunctionTypedFormalParameter node) { |
| 1265 UnlinkedParamBuilder b = serializeParameter(node); |
| 1266 b.isFunctionTyped = true; |
| 1267 serializeFunctionTypedParameterDetails(b, node.returnType, node.parameters); |
| 1268 return b; |
| 1269 } |
| 1270 |
| 1271 @override |
| 1272 void visitImportDirective(ImportDirective node) { |
| 1273 UnlinkedImportBuilder b = new UnlinkedImportBuilder(); |
| 1274 b.annotations = serializeAnnotations(node.metadata); |
| 1275 if (node.uri.stringValue == 'dart:core') { |
| 1276 hasCoreBeenImported = true; |
| 1277 } |
| 1278 b.offset = node.offset; |
| 1279 b.combinators = node.combinators.map(serializeCombinator).toList(); |
| 1280 b.configurations = node.configurations.map(serializeConfiguration).toList(); |
| 1281 if (node.prefix != null) { |
| 1282 b.prefixReference = serializeReference(null, node.prefix.name); |
| 1283 b.prefixOffset = node.prefix.offset; |
| 1284 } |
| 1285 b.isDeferred = node.deferredKeyword != null; |
| 1286 b.uri = node.uri.stringValue; |
| 1287 b.uriOffset = node.uri.offset; |
| 1288 b.uriEnd = node.uri.end; |
| 1289 unlinkedImports.add(b); |
| 1290 } |
| 1291 |
| 1292 @override |
| 1293 void visitLabel(Label node) { |
| 1294 AstNode parent = node.parent; |
| 1295 if (parent is! NamedExpression) { |
| 1296 labels.add(new UnlinkedLabelBuilder( |
| 1297 name: node.label.name, |
| 1298 nameOffset: node.offset, |
| 1299 isOnSwitchMember: parent is SwitchMember, |
| 1300 isOnSwitchStatement: parent is LabeledStatement && |
| 1301 parent.statement is SwitchStatement)); |
| 1302 } |
| 1303 } |
| 1304 |
| 1305 @override |
| 1306 void visitLibraryDirective(LibraryDirective node) { |
| 1307 libraryName = |
| 1308 node.name.components.map((SimpleIdentifier id) => id.name).join('.'); |
| 1309 libraryNameOffset = node.name.offset; |
| 1310 libraryNameLength = node.name.length; |
| 1311 isCoreLibrary = libraryName == 'dart.core'; |
| 1312 libraryDocumentationComment = |
| 1313 serializeDocumentation(node.documentationComment); |
| 1314 libraryAnnotations = serializeAnnotations(node.metadata); |
| 1315 } |
| 1316 |
| 1317 @override |
| 1318 void visitMethodDeclaration(MethodDeclaration node) { |
| 1319 executables.add(serializeExecutable( |
| 1320 node, |
| 1321 node.name.name, |
| 1322 node.name.offset, |
| 1323 node.isGetter, |
| 1324 node.isSetter, |
| 1325 node.returnType, |
| 1326 node.parameters, |
| 1327 node.body, |
| 1328 false, |
| 1329 node.isStatic, |
| 1330 node.documentationComment, |
| 1331 node.metadata, |
| 1332 node.typeParameters, |
| 1333 node.externalKeyword != null, |
| 1334 false)); |
| 1335 } |
| 1336 |
| 1337 @override |
| 1338 void visitPartDirective(PartDirective node) { |
| 1339 parts.add(new UnlinkedPartBuilder( |
| 1340 uriOffset: node.uri.offset, |
| 1341 uriEnd: node.uri.end, |
| 1342 annotations: serializeAnnotations(node.metadata))); |
| 1343 } |
| 1344 |
| 1345 @override |
| 1346 void visitPartOfDirective(PartOfDirective node) { |
| 1347 isCoreLibrary = node.libraryName.name == 'dart.core'; |
| 1348 } |
| 1349 |
| 1350 @override |
| 1351 UnlinkedParamBuilder visitSimpleFormalParameter(SimpleFormalParameter node) { |
| 1352 UnlinkedParamBuilder b = serializeParameter(node); |
| 1353 b.type = serializeTypeName(node.type); |
| 1354 return b; |
| 1355 } |
| 1356 |
| 1357 @override |
| 1358 void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| 1359 serializeVariables(null, node.variables, false, node.documentationComment, |
| 1360 node.metadata, false); |
| 1361 } |
| 1362 |
| 1363 @override |
| 1364 UnlinkedTypeParamBuilder visitTypeParameter(TypeParameter node) { |
| 1365 UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder(); |
| 1366 b.name = node.name.name; |
| 1367 b.nameOffset = node.name.offset; |
| 1368 if (node.bound != null) { |
| 1369 b.bound = serializeTypeName(node.bound); |
| 1370 } |
| 1371 b.annotations = serializeAnnotations(node.metadata); |
| 1372 b.codeRange = serializeCodeRange(node); |
| 1373 return b; |
| 1374 } |
| 1375 |
| 1376 @override |
| 1377 void visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| 1378 serializeVariables( |
| 1379 enclosingBlock, node.variables, false, null, null, false); |
| 1380 } |
| 1381 |
| 1382 /** |
| 1383 * Helper method to determine if a given [typeName] refers to `dynamic`. |
| 1384 */ |
| 1385 static bool isDynamic(TypeName typeName) { |
| 1386 Identifier name = typeName.name; |
| 1387 return name is SimpleIdentifier && name.name == 'dynamic'; |
| 1388 } |
| 1389 } |
| 1390 |
| 1391 /** |
| 1392 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s. |
| 1393 */ |
| 1394 class _TypeParameterScope extends _Scope { |
| 1395 /** |
| 1396 * Get the number of [_ScopedTypeParameter]s defined in this |
| 1397 * [_TypeParameterScope]. |
| 1398 */ |
| 1399 int get length => _definedNames.length; |
| 1400 } |
| OLD | NEW |