Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2015, 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.elements; | |
| 6 | |
| 7 import 'package:analyzer/src/generated/element.dart'; | |
| 8 import 'package:analyzer/src/generated/resolver.dart'; | |
| 9 import 'package:analyzer/src/generated/utilities_dart.dart'; | |
| 10 import 'package:analyzer/src/summary/builder.dart'; | |
| 11 import 'package:analyzer/src/summary/format.dart'; | |
| 12 | |
| 13 /** | |
| 14 * Serialize all the elements in [lib] to a summary using [ctx] as the context | |
| 15 * for building the summary, and using [typeProvider] to find built-in types. | |
| 16 * | |
| 17 * Return an object which may safely be passed to [BuilderContext.getBuffer] or | |
| 18 * included in an aggregate summary. | |
| 19 */ | |
| 20 Object serializeLibrary( | |
|
Brian Wilkerson
2015/11/11 15:26:10
The class 'Object' is used a lot in this library.
Paul Berry
2015/11/11 19:12:22
Yeah, I'm not happy about that either. I have an
| |
| 21 BuilderContext ctx, LibraryElement lib, TypeProvider typeProvider) { | |
| 22 return new _LibrarySerializer(ctx, lib, typeProvider).serializeLibrary(); | |
| 23 } | |
| 24 | |
| 25 /** | |
| 26 * Instances of this class keep track of intermediate state during | |
| 27 * serialization of a single library.` | |
| 28 */ | |
| 29 class _LibrarySerializer { | |
| 30 /** | |
| 31 * The library to be serialized. | |
| 32 */ | |
| 33 final LibraryElement libraryElement; | |
| 34 | |
| 35 /** | |
| 36 * The type provider. This is used to locate the library for `dart:core`. | |
| 37 */ | |
| 38 final TypeProvider typeProvider; | |
| 39 | |
| 40 /** | |
| 41 * List of objects which should be written to [UnlinkedLibrary.classes]. | |
| 42 */ | |
| 43 final List<Object> classes = <Object>[]; | |
| 44 | |
| 45 /** | |
| 46 * List of objects which should be written to [UnlinkedLibrary.enums]. | |
| 47 */ | |
| 48 final List<Object> enums = <Object>[]; | |
| 49 | |
| 50 /** | |
| 51 * List of objects which should be written to [UnlinkedLibrary.executables]. | |
| 52 */ | |
| 53 final List<Object> executables = <Object>[]; | |
| 54 | |
| 55 /** | |
| 56 * List of objects which should be written to [UnlinkedLibrary.typedefs]. | |
| 57 */ | |
| 58 final List<Object> typedefs = <Object>[]; | |
| 59 | |
| 60 /** | |
| 61 * List of objects which should be written to [UnlinkedLibrary.units]. | |
| 62 */ | |
| 63 final List<Object> units = <Object>[]; | |
| 64 | |
| 65 /** | |
| 66 * List of objects which should be written to [UnlinkedLibrary.variables]. | |
| 67 */ | |
| 68 final List<Object> variables = <Object>[]; | |
| 69 | |
| 70 /** | |
| 71 * Map from [LibraryElement] to the index of the entry in the "dependency | |
| 72 * table" that refers to it. | |
| 73 */ | |
| 74 final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{}; | |
| 75 | |
| 76 /** | |
| 77 * The "dependency table". This is the list of objects which should be | |
| 78 * written to [PrelinkedLibrary.dependencies]. | |
| 79 */ | |
| 80 final List<Object> dependencies = <Object>[]; | |
| 81 | |
| 82 /** | |
| 83 * The unlinked portion of the "imports table". This is the list of objects | |
| 84 * which should be written to [UnlinkedLibrary.imports]. | |
| 85 */ | |
| 86 final List<Object> unlinkedImports = <Object>[]; | |
| 87 | |
| 88 /** | |
| 89 * The prelinked portion of the "imports table". This is the list of ints | |
| 90 * which should be written to [PrelinkedLibrary.imports]. | |
| 91 */ | |
| 92 final List<Object> prelinkedImports = <int>[]; | |
| 93 | |
| 94 /** | |
| 95 * Map from prefix [String] to the index of the entry in the "prefix" table | |
| 96 * that refers to it. The empty prefix is not included in this map. | |
| 97 */ | |
| 98 final Map<String, int> prefixMap = <String, int>{}; | |
| 99 | |
| 100 /** | |
| 101 * The "prefix table". This is the list of objects which should be written | |
| 102 * to [UnlinkedLibrary.prefixes]. | |
| 103 */ | |
| 104 final List<Object> prefixes = <Object>[]; | |
| 105 | |
| 106 /** | |
| 107 * Map from [Element] to the index of the entry in the "references table" | |
| 108 * that refers to it. | |
| 109 */ | |
| 110 final Map<Element, int> referenceMap = <Element, int>{}; | |
| 111 | |
| 112 /** | |
| 113 * The unlinked portion of the "references table". This is the list of | |
| 114 * objects which should be written to [UnlinkedLibrary.references]. | |
| 115 */ | |
| 116 final List<Object> unlinkedReferences = <Object>[]; | |
| 117 | |
| 118 /** | |
| 119 * The prelinked portion of the "references table". This is the list of | |
| 120 * objects which should be written to [PrelinkedLibrary.references]. | |
| 121 */ | |
| 122 final List<Object> prelinkedReferences = <Object>[]; | |
| 123 | |
| 124 //final Map<String, int> prefixIndices = <String, int>{}; | |
| 125 | |
| 126 /** | |
| 127 * Index into the "references table" representing `dynamic`, if such an index | |
| 128 * exists. `null` if no such entry has been made in the references table | |
| 129 * yet. | |
| 130 */ | |
| 131 int dynamicReferenceIndex = null; | |
| 132 | |
| 133 /** | |
| 134 * Index into the "references table" representing an unresolved reference, if | |
| 135 * such an index exists. `null` if no such entry has been made in the | |
| 136 * references table yet. | |
| 137 */ | |
| 138 int unresolvedReferenceIndex = null; | |
| 139 | |
| 140 /** | |
| 141 * Set of libraries which have been seen so far while visiting the transitive | |
| 142 * closure of exports. | |
| 143 */ | |
| 144 final Set<LibraryElement> librariesAddedToTransitiveExportClosure = | |
| 145 new Set<LibraryElement>(); | |
| 146 | |
| 147 /** | |
| 148 * [BuilderContext] used to serialize the output summary. | |
| 149 */ | |
| 150 final BuilderContext ctx; | |
| 151 | |
| 152 _LibrarySerializer(this.ctx, this.libraryElement, this.typeProvider) { | |
| 153 dependencies.add(encodePrelinkedDependency(ctx)); | |
| 154 dependencyMap[libraryElement] = 0; | |
| 155 prefixes.add(encodeUnlinkedPrefix(ctx)); | |
| 156 } | |
| 157 | |
| 158 /** | |
| 159 * Retrieve the library element for `dart:core`. | |
| 160 */ | |
| 161 LibraryElement get coreLibrary => typeProvider.objectType.element.library; | |
| 162 | |
| 163 /** | |
| 164 * Add all classes, enums, typedefs, executables, and top level variables | |
| 165 * from the given compilation unit [element] to the library summary. | |
| 166 * [unitNum] indicates the ordinal position of this compilation unit in the | |
| 167 * library. | |
| 168 */ | |
| 169 void addCompilationUnitElements(CompilationUnitElement element, int unitNum) { | |
| 170 UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(ctx); | |
| 171 if (element.uri != null) { | |
| 172 b.uri = element.uri; | |
| 173 } | |
| 174 units.add(b.finish()); | |
| 175 for (ClassElement cls in element.types) { | |
| 176 classes.add(serializeClass(cls, unitNum)); | |
| 177 } | |
| 178 for (ClassElement e in element.enums) { | |
| 179 enums.add(serializeEnum(e, unitNum)); | |
| 180 } | |
| 181 for (FunctionTypeAliasElement type in element.functionTypeAliases) { | |
| 182 typedefs.add(serializeTypedef(type, unitNum)); | |
| 183 } | |
| 184 for (FunctionElement executable in element.functions) { | |
| 185 executables.add(serializeExecutable(executable, unitNum)); | |
| 186 } | |
| 187 for (PropertyAccessorElement accessor in element.accessors) { | |
| 188 if (!accessor.isSynthetic) { | |
| 189 executables.add(serializeExecutable(accessor, unitNum)); | |
| 190 } else if (accessor.isGetter) { | |
| 191 PropertyInducingElement variable = accessor.variable; | |
| 192 if (variable != null && !variable.isSynthetic) { | |
|
Brian Wilkerson
2015/11/11 15:26:10
Under what conditions will the variable be non-syn
Paul Berry
2015/11/11 19:12:22
Did you perhaps mean to ask "Under what conditions
| |
| 193 variables.add(serializeVariable(variable, unitNum)); | |
| 194 } | |
| 195 } | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 /** | |
| 200 * Add [exportedLibrary] (and the transitive closure of all libraries it | |
| 201 * exports) to the dependency table ([PrelinkedLibrary.dependencies]). | |
| 202 */ | |
| 203 void addTransitiveExportClosure(LibraryElement exportedLibrary) { | |
| 204 if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) { | |
| 205 serializeDependency(exportedLibrary); | |
| 206 for (LibraryElement transitiveExport | |
| 207 in exportedLibrary.exportedLibraries) { | |
| 208 addTransitiveExportClosure(transitiveExport); | |
| 209 } | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 /** | |
| 214 * Compute the appropriate De Bruijn index to represent the given type | |
| 215 * parameter [type]. | |
| 216 */ | |
| 217 int findTypeParameterIndex(TypeParameterType type) { | |
| 218 int index = 0; | |
| 219 Element enclosingElement = type.element.enclosingElement; | |
| 220 while (enclosingElement != null) { | |
| 221 List<TypeParameterElement> typeParameters; | |
| 222 if (enclosingElement is ClassElement) { | |
| 223 typeParameters = enclosingElement.typeParameters; | |
| 224 } else if (enclosingElement is FunctionTypeAliasElement) { | |
| 225 // TODO(paulberry): test this. | |
| 226 typeParameters = enclosingElement.typeParameters; | |
| 227 } | |
| 228 for (int i = 0; i < typeParameters.length; i++) { | |
| 229 TypeParameterElement param = typeParameters[i]; | |
| 230 if (param == type.element) { | |
| 231 return index + typeParameters.length - i; | |
| 232 } | |
| 233 } | |
| 234 index += typeParameters.length; | |
| 235 enclosingElement = enclosingElement.enclosingElement; | |
| 236 } | |
| 237 throw new StateError('Unbound type parameter $type'); | |
| 238 } | |
| 239 | |
| 240 /** | |
| 241 * Serialize the given [classElement], which exists in the unit numbered | |
| 242 * [unitNum], creating an [UnlinkedClass]. | |
| 243 */ | |
| 244 Object serializeClass(ClassElement classElement, int unitNum) { | |
| 245 UnlinkedClassBuilder b = new UnlinkedClassBuilder(ctx); | |
| 246 b.name = classElement.name; | |
| 247 b.unit = unitNum; | |
| 248 b.typeParameters = | |
| 249 classElement.typeParameters.map(serializeTypeParam).toList(); | |
| 250 if (classElement.supertype != null && !classElement.supertype.isObject) { | |
| 251 b.supertype = serializeTypeRef(classElement.supertype); | |
| 252 } | |
| 253 b.mixins = classElement.mixins.map(serializeTypeRef).toList(); | |
| 254 b.interfaces = classElement.interfaces.map(serializeTypeRef).toList(); | |
| 255 List<Object> fields = <Object>[]; | |
| 256 List<Object> executables = <Object>[]; | |
| 257 for (ConstructorElement executable in classElement.constructors) { | |
| 258 if (!executable.isSynthetic) { | |
| 259 executables.add(serializeExecutable(executable, 0)); | |
| 260 } | |
| 261 } | |
| 262 for (MethodElement executable in classElement.methods) { | |
| 263 executables.add(serializeExecutable(executable, 0)); | |
| 264 } | |
| 265 for (PropertyAccessorElement accessor in classElement.accessors) { | |
| 266 if (!accessor.isSynthetic) { | |
| 267 executables.add(serializeExecutable(accessor, 0)); | |
| 268 } else if (accessor.isGetter) { | |
| 269 PropertyInducingElement field = accessor.variable; | |
| 270 if (field != null && !field.isSynthetic) { | |
| 271 fields.add(serializeVariable(field, 0)); | |
| 272 } | |
| 273 } | |
| 274 } | |
| 275 b.fields = fields; | |
| 276 b.executables = executables; | |
| 277 b.isAbstract = classElement.isAbstract; | |
| 278 b.isMixinApplication = classElement.isMixinApplication; | |
| 279 return b.finish(); | |
| 280 } | |
| 281 | |
| 282 /** | |
| 283 * Serialize the given [combinator] into an [UnlinkedCombinator]. | |
| 284 */ | |
| 285 Object serializeCombinator(NamespaceCombinator combinator) { | |
| 286 UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder(ctx); | |
| 287 if (combinator is ShowElementCombinator) { | |
| 288 b.shows = combinator.shownNames.map(serializeCombinatorName).toList(); | |
| 289 } else if (combinator is HideElementCombinator) { | |
| 290 b.hides = combinator.hiddenNames.map(serializeCombinatorName).toList(); | |
| 291 } | |
| 292 return b.finish(); | |
| 293 } | |
| 294 | |
| 295 /** | |
| 296 * Serialize the given [name] into an [UnlinkedCombinatorName]. | |
| 297 */ | |
| 298 Object serializeCombinatorName(String name) { | |
| 299 return encodeUnlinkedCombinatorName(ctx, name: name); | |
| 300 } | |
| 301 | |
| 302 /** | |
| 303 * Return the index of the entry in the dependency table | |
| 304 * ([PrelinkedLibrary.dependencies]) for the given [dependentLibrary]. A new | |
| 305 * entry is added to the table if necessary to satisfy the request. | |
| 306 */ | |
| 307 int serializeDependency(LibraryElement dependentLibrary) { | |
| 308 return dependencyMap.putIfAbsent(dependentLibrary, () { | |
| 309 int index = dependencies.length; | |
| 310 dependencies.add(encodePrelinkedDependency(ctx, | |
| 311 uri: dependentLibrary.source.uri.toString())); | |
| 312 return index; | |
| 313 }); | |
| 314 } | |
| 315 | |
| 316 /** | |
| 317 * Return the index of the entry in the references table | |
| 318 * ([UnlinkedLibrary.references] and [PrelinkedLibrary.references]) | |
| 319 * representing the pseudo-type `dynamic`. A new entry is added to the table | |
| 320 * if necessary to satisfy the request. | |
| 321 */ | |
| 322 int serializeDynamicReference() { | |
| 323 if (dynamicReferenceIndex == null) { | |
| 324 assert(unlinkedReferences.length == prelinkedReferences.length); | |
| 325 dynamicReferenceIndex = unlinkedReferences.length; | |
| 326 unlinkedReferences.add(encodeUnlinkedReference(ctx)); | |
| 327 prelinkedReferences.add(encodePrelinkedReference(ctx, | |
| 328 kind: PrelinkedReferenceKind.classOrEnum)); | |
| 329 } | |
| 330 return dynamicReferenceIndex; | |
| 331 } | |
| 332 | |
| 333 /** | |
| 334 * Serialize the given [enumElement], which exists in the unit numbered | |
| 335 * [unitNum], creating an [UnlinkedEnum]. | |
| 336 */ | |
| 337 Object serializeEnum(ClassElement enumElement, int unitNum) { | |
| 338 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(ctx); | |
| 339 b.name = enumElement.name; | |
| 340 List<Object> values = <Object>[]; | |
| 341 for (FieldElement field in enumElement.fields) { | |
| 342 if (field.isConst && field.type.element == enumElement) { | |
| 343 values.add(encodeUnlinkedEnumValue(ctx, name: field.name)); | |
| 344 } | |
| 345 } | |
| 346 b.values = values; | |
| 347 b.unit = unitNum; | |
| 348 return b.finish(); | |
| 349 } | |
| 350 | |
| 351 /** | |
| 352 * Serialize the given [executableElement], which exists in the unit numbered | |
| 353 * [unitNum], creating an [UnlinkedExecutable]. For elements declared inside | |
| 354 * a class, [unitNum] should be zero. | |
| 355 */ | |
| 356 Object serializeExecutable(ExecutableElement executableElement, int unitNum) { | |
| 357 if (executableElement.enclosingElement is ClassElement) { | |
| 358 assert(unitNum == 0); | |
| 359 } | |
| 360 UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder(ctx); | |
| 361 b.name = executableElement.name; | |
| 362 b.unit = unitNum; | |
| 363 if (!executableElement.type.returnType.isVoid) { | |
| 364 b.returnType = serializeTypeRef(executableElement.type.returnType); | |
| 365 } | |
| 366 // TODO(paulberry): serialize type parameters. | |
| 367 b.parameters = | |
| 368 executableElement.type.parameters.map(serializeParam).toList(); | |
| 369 if (executableElement is PropertyAccessorElement) { | |
| 370 if (executableElement.isGetter) { | |
| 371 b.kind = UnlinkedExecutableKind.getter; | |
| 372 } else { | |
| 373 b.kind = UnlinkedExecutableKind.setter; | |
| 374 } | |
| 375 } else if (executableElement is ConstructorElement) { | |
| 376 b.kind = UnlinkedExecutableKind.constructor; | |
| 377 b.isConst = executableElement.isConst; | |
| 378 b.isFactory = executableElement.isFactory; | |
| 379 } else { | |
| 380 b.kind = UnlinkedExecutableKind.functionOrMethod; | |
| 381 } | |
| 382 b.isAbstract = executableElement.isAbstract; | |
| 383 b.isStatic = executableElement.isStatic && | |
| 384 executableElement.enclosingElement is ClassElement; | |
| 385 return b.finish(); | |
| 386 } | |
| 387 | |
| 388 /** | |
| 389 * Serialize the given [exportElement] into an [UnlinkedExport]. | |
| 390 */ | |
| 391 Object serializeExport(ExportElement exportElement) { | |
| 392 UnlinkedExportBuilder b = new UnlinkedExportBuilder(ctx); | |
| 393 b.uri = exportElement.uri; | |
| 394 b.combinators = exportElement.combinators.map(serializeCombinator).toList(); | |
| 395 return b.finish(); | |
| 396 } | |
| 397 | |
| 398 /** | |
| 399 * Serialize the given [importElement], adding information about it to | |
| 400 * the [unlinkedImports] and [prelinkedImports] lists. | |
| 401 */ | |
| 402 void serializeImport(ImportElement importElement) { | |
| 403 assert(unlinkedImports.length == prelinkedImports.length); | |
| 404 UnlinkedImportBuilder b = new UnlinkedImportBuilder(ctx); | |
| 405 b.isDeferred = importElement.isDeferred; | |
| 406 b.offset = importElement.nameOffset; | |
| 407 b.combinators = importElement.combinators.map(serializeCombinator).toList(); | |
| 408 if (importElement.prefix != null) { | |
| 409 b.prefix = prefixMap.putIfAbsent(importElement.prefix.name, () { | |
| 410 int index = prefixes.length; | |
| 411 prefixes | |
| 412 .add(encodeUnlinkedPrefix(ctx, name: importElement.prefix.name)); | |
| 413 return index; | |
| 414 }); | |
| 415 } | |
| 416 if (importElement.isSynthetic) { | |
| 417 b.isImplicit = true; | |
| 418 } else { | |
| 419 b.uri = importElement.uri; | |
| 420 } | |
| 421 addTransitiveExportClosure(importElement.importedLibrary); | |
| 422 unlinkedImports.add(b.finish()); | |
| 423 prelinkedImports.add(serializeDependency(importElement.importedLibrary)); | |
| 424 } | |
| 425 | |
| 426 /** | |
| 427 * Serialize the whole library element into a [PrelinkedLibrary]. Should be | |
| 428 * called exactly once for each instance of [_LibrarySerializer]. | |
| 429 */ | |
| 430 Object serializeLibrary() { | |
| 431 UnlinkedLibraryBuilder ub = new UnlinkedLibraryBuilder(ctx); | |
| 432 PrelinkedLibraryBuilder pb = new PrelinkedLibraryBuilder(ctx); | |
| 433 if (libraryElement.name.isNotEmpty) { | |
| 434 ub.name = libraryElement.name; | |
| 435 } | |
| 436 for (ImportElement importElement in libraryElement.imports) { | |
| 437 serializeImport(importElement); | |
| 438 } | |
| 439 ub.exports = libraryElement.exports.map(serializeExport).toList(); | |
| 440 addCompilationUnitElements(libraryElement.definingCompilationUnit, 0); | |
| 441 for (int i = 0; i < libraryElement.parts.length; i++) { | |
| 442 addCompilationUnitElements(libraryElement.parts[i], i + 1); | |
| 443 } | |
| 444 ub.classes = classes; | |
| 445 ub.enums = enums; | |
| 446 ub.executables = executables; | |
| 447 ub.imports = unlinkedImports; | |
| 448 ub.prefixes = prefixes; | |
| 449 ub.references = unlinkedReferences; | |
| 450 ub.typedefs = typedefs; | |
| 451 ub.units = units; | |
| 452 ub.variables = variables; | |
| 453 pb.unlinked = ub.finish(); | |
| 454 pb.dependencies = dependencies; | |
| 455 pb.importDependencies = prelinkedImports; | |
| 456 pb.references = prelinkedReferences; | |
| 457 return pb.finish(); | |
| 458 } | |
| 459 | |
| 460 /** | |
| 461 * Serialize the given [parameter] into an [UnlinkedParam]. | |
| 462 */ | |
| 463 Object serializeParam(ParameterElement parameter) { | |
| 464 UnlinkedParamBuilder b = new UnlinkedParamBuilder(ctx); | |
| 465 b.name = parameter.name; | |
| 466 switch (parameter.parameterKind) { | |
| 467 case ParameterKind.REQUIRED: | |
| 468 b.kind = UnlinkedParamKind.required; | |
| 469 break; | |
| 470 case ParameterKind.POSITIONAL: | |
| 471 b.kind = UnlinkedParamKind.positional; | |
| 472 break; | |
| 473 case ParameterKind.NAMED: | |
| 474 b.kind = UnlinkedParamKind.named; | |
| 475 break; | |
| 476 } | |
| 477 b.isInitializingFormal = parameter.isInitializingFormal; | |
| 478 DartType type = parameter.type; | |
| 479 if (type is FunctionType) { | |
| 480 b.isFunctionTyped = true; | |
| 481 if (!type.returnType.isVoid) { | |
| 482 b.type = serializeTypeRef(type.returnType); | |
| 483 } | |
| 484 b.parameters = type.parameters.map(serializeParam).toList(); | |
| 485 } else { | |
| 486 b.type = serializeTypeRef(type); | |
| 487 } | |
| 488 return b.finish(); | |
| 489 } | |
| 490 | |
| 491 /** | |
| 492 * Serialize the given [typedefElement], which exists in the unit numbered | |
| 493 * [unitNum], creating an [UnlinkedTypedef]. | |
| 494 */ | |
| 495 Object serializeTypedef( | |
| 496 FunctionTypeAliasElement typedefElement, int unitNum) { | |
| 497 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder(ctx); | |
| 498 b.name = typedefElement.name; | |
| 499 b.unit = unitNum; | |
| 500 b.typeParameters = | |
| 501 typedefElement.typeParameters.map(serializeTypeParam).toList(); | |
| 502 if (!typedefElement.returnType.isVoid) { | |
| 503 b.returnType = serializeTypeRef(typedefElement.returnType); | |
| 504 } | |
| 505 b.parameters = typedefElement.parameters.map(serializeParam).toList(); | |
| 506 return b.finish(); | |
| 507 } | |
| 508 | |
| 509 /** | |
| 510 * Serialize the given [typeParameter] into an [UnlinkedTypeParam]. | |
| 511 */ | |
| 512 Object serializeTypeParam(TypeParameterElement typeParameter) { | |
| 513 UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder(ctx); | |
| 514 b.name = typeParameter.name; | |
| 515 if (typeParameter.bound != null) { | |
| 516 b.bound = serializeTypeRef(typeParameter.bound); | |
| 517 } | |
| 518 return b.finish(); | |
| 519 } | |
| 520 | |
| 521 /** | |
| 522 * Serialize the given [type] into an [UnlinkedTypeRef]. | |
| 523 */ | |
| 524 Object serializeTypeRef(DartType type) { | |
| 525 UnlinkedTypeRefBuilder b = new UnlinkedTypeRefBuilder(ctx); | |
| 526 if (type is TypeParameterType) { | |
| 527 Element enclosingElement = type.element.enclosingElement; | |
| 528 b.paramReference = findTypeParameterIndex(type); | |
| 529 } else { | |
| 530 Element element = type.element; | |
| 531 CompilationUnitElement dependentCompilationUnit = | |
| 532 element.getAncestor((Element e) => e is CompilationUnitElement); | |
| 533 LibraryElement dependentLibrary = element.library; | |
| 534 if (dependentLibrary == null) { | |
| 535 assert(type.isDynamic); | |
| 536 if (type is UndefinedTypeImpl) { | |
| 537 b.reference = serializeUnresolvedReference(); | |
| 538 } else { | |
| 539 b.reference = serializeDynamicReference(); | |
| 540 } | |
| 541 } else { | |
| 542 b.reference = referenceMap.putIfAbsent(element, () { | |
| 543 assert(unlinkedReferences.length == prelinkedReferences.length); | |
| 544 int index = unlinkedReferences.length; | |
| 545 // TODO(paulberry): set UnlinkedReference.prefix. | |
| 546 unlinkedReferences | |
| 547 .add(encodeUnlinkedReference(ctx, name: element.name)); | |
| 548 prelinkedReferences.add(encodePrelinkedReference(ctx, | |
| 549 dependency: serializeDependency(dependentLibrary), | |
| 550 kind: element is FunctionTypeAliasElement | |
| 551 ? PrelinkedReferenceKind.typedef | |
| 552 : PrelinkedReferenceKind.classOrEnum)); | |
| 553 return index; | |
| 554 }); | |
| 555 } | |
| 556 List<DartType> typeArguments; | |
| 557 if (type is InterfaceType) { | |
| 558 typeArguments = type.typeArguments; | |
| 559 } else if (type is FunctionType) { | |
| 560 typeArguments = type.typeArguments; | |
| 561 } | |
| 562 if (typeArguments != null && | |
| 563 typeArguments.any((DartType argument) => !argument.isDynamic)) { | |
| 564 b.typeArguments = typeArguments.map(serializeTypeRef).toList(); | |
| 565 } | |
| 566 } | |
| 567 return b.finish(); | |
| 568 } | |
| 569 | |
| 570 /** | |
| 571 * Return the index of the entry in the references table | |
| 572 * ([UnlinkedLibrary.references] and [PrelinkedLibrary.references]) used for | |
| 573 * unresolved references. A new entry is added to the table if necessary to | |
| 574 * satisfy the request. | |
| 575 */ | |
| 576 int serializeUnresolvedReference() { | |
| 577 // TODO(paulberry): in order for relinking to work, we need to record the | |
| 578 // name and prefix of the unresolved symbol. This is not (yet) encoded in | |
| 579 // the element model. | |
| 580 if (unresolvedReferenceIndex == null) { | |
| 581 assert(unlinkedReferences.length == prelinkedReferences.length); | |
| 582 unresolvedReferenceIndex = unlinkedReferences.length; | |
| 583 unlinkedReferences.add(encodeUnlinkedReference(ctx)); | |
| 584 prelinkedReferences.add(encodePrelinkedReference(ctx, | |
| 585 kind: PrelinkedReferenceKind.unresolved)); | |
| 586 } | |
| 587 return unresolvedReferenceIndex; | |
| 588 } | |
| 589 | |
| 590 /** | |
| 591 * Serialize the given [variable], which exists in the unit numbered | |
| 592 * [unitNum], creating an [UnlinkedVariable]. For variables declared inside | |
| 593 * a class (i.e. fields), [unitNum] should be zero. | |
| 594 */ | |
| 595 Object serializeVariable(PropertyInducingElement variable, int unitNum) { | |
| 596 if (variable.enclosingElement is ClassElement) { | |
| 597 assert(unitNum == 0); | |
| 598 } | |
| 599 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(ctx); | |
| 600 b.name = variable.name; | |
| 601 b.unit = unitNum; | |
| 602 b.type = serializeTypeRef(variable.type); | |
| 603 b.isStatic = variable.isStatic && variable.enclosingElement is ClassElement; | |
| 604 b.isFinal = variable.isFinal; | |
| 605 b.isConst = variable.isConst; | |
| 606 return b.finish(); | |
| 607 } | |
| 608 } | |
| OLD | NEW |