Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(771)

Side by Side Diff: pkg/analyzer/lib/src/summary/summarize_elements.dart

Issue 2353773002: Remove 'serializeLibrary(LibraryElement)' and its tests. (Closed)
Patch Set: Actually run strong mode AST based resynthesize. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/prelinker_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library serialization.elements; 5 library serialization.elements;
6 6
7 import 'dart:convert'; 7 import 'dart:convert';
8 8
9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/element/element.dart';
11 import 'package:analyzer/dart/element/type.dart';
12 import 'package:analyzer/src/dart/element/element.dart';
13 import 'package:analyzer/src/dart/element/member.dart';
14 import 'package:analyzer/src/dart/element/type.dart';
15 import 'package:analyzer/src/generated/resolver.dart';
16 import 'package:analyzer/src/generated/source.dart'; 9 import 'package:analyzer/src/generated/source.dart';
17 import 'package:analyzer/src/generated/utilities_dart.dart';
18 import 'package:analyzer/src/summary/api_signature.dart'; 10 import 'package:analyzer/src/summary/api_signature.dart';
19 import 'package:analyzer/src/summary/format.dart'; 11 import 'package:analyzer/src/summary/format.dart';
20 import 'package:analyzer/src/summary/idl.dart'; 12 import 'package:analyzer/src/summary/idl.dart';
21 import 'package:analyzer/src/summary/name_filter.dart';
22 import 'package:analyzer/src/summary/package_bundle_reader.dart'; 13 import 'package:analyzer/src/summary/package_bundle_reader.dart';
23 import 'package:analyzer/src/summary/summarize_const_expr.dart';
24 import 'package:convert/convert.dart'; 14 import 'package:convert/convert.dart';
25 import 'package:crypto/crypto.dart'; 15 import 'package:crypto/crypto.dart';
26 16
27 /** 17 /**
28 * Serialize all the elements in [lib] to a summary using [ctx] as the context
29 * for building the summary, and using [typeProvider] to find built-in types.
30 */
31 LibrarySerializationResult serializeLibrary(
32 LibraryElement lib, TypeProvider typeProvider, bool strongMode) {
33 _LibrarySerializer serializer =
34 new _LibrarySerializer(lib, typeProvider, strongMode);
35 LinkedLibraryBuilder linked = serializer.serializeLibrary();
36 return new LibrarySerializationResult(linked, serializer.unlinkedUnits,
37 serializer.unitUris, serializer.unitSources);
38 }
39
40 ReferenceKind _getReferenceKind(Element element) {
41 if (element == null ||
42 element is ClassElement ||
43 element is DynamicElementImpl) {
44 return ReferenceKind.classOrEnum;
45 } else if (element is ConstructorElement) {
46 return ReferenceKind.constructor;
47 } else if (element is FunctionElement) {
48 if (element.enclosingElement is CompilationUnitElement) {
49 return ReferenceKind.topLevelFunction;
50 }
51 return ReferenceKind.function;
52 } else if (element is FunctionTypeAliasElement) {
53 return ReferenceKind.typedef;
54 } else if (element is PropertyAccessorElement) {
55 if (element.enclosingElement is ClassElement) {
56 return ReferenceKind.propertyAccessor;
57 }
58 return ReferenceKind.topLevelPropertyAccessor;
59 } else if (element is MethodElement) {
60 return ReferenceKind.method;
61 } else if (element is TopLevelVariableElement) {
62 // Summaries don't need to distinguish between references to a variable and
63 // references to its getter.
64 return ReferenceKind.topLevelPropertyAccessor;
65 } else if (element is LocalVariableElement) {
66 return ReferenceKind.variable;
67 } else if (element is FieldElement) {
68 // Summaries don't need to distinguish between references to a field and
69 // references to its getter.
70 return ReferenceKind.propertyAccessor;
71 } else {
72 throw new Exception('Unexpected element kind: ${element.runtimeType}');
73 }
74 }
75
76 /**
77 * Type of closures used by [_LibrarySerializer] to defer generation of
78 * [EntityRefBuilder] objects until the end of serialization of a
79 * compilation unit.
80 */
81 typedef EntityRefBuilder _SerializeTypeRef();
82
83 /**
84 * Data structure holding the result of serializing a [LibraryElement].
85 */
86 class LibrarySerializationResult {
87 /**
88 * Linked information the given library.
89 */
90 final LinkedLibraryBuilder linked;
91
92 /**
93 * Unlinked information for the compilation units constituting the library.
94 * The zeroth entry in the list is the defining compilation unit; the
95 * remaining entries are the parts, in the order listed in the defining
96 * compilation unit's part declarations.
97 */
98 final List<UnlinkedUnitBuilder> unlinkedUnits;
99
100 /**
101 * Absolute URI of each compilation unit appearing in the library.
102 */
103 final List<String> unitUris;
104
105 /**
106 * Source object corresponding to each compilation unit appearing in the
107 * library.
108 */
109 final List<Source> unitSources;
110
111 LibrarySerializationResult(
112 this.linked, this.unlinkedUnits, this.unitUris, this.unitSources);
113 }
114
115 /**
116 * Object that gathers information uses it to assemble a new 18 * Object that gathers information uses it to assemble a new
117 * [PackageBundleBuilder]. 19 * [PackageBundleBuilder].
118 */ 20 */
119 class PackageBundleAssembler { 21 class PackageBundleAssembler {
120 /** 22 /**
121 * Value that will be stored in [PackageBundle.majorVersion] for any summaries 23 * Value that will be stored in [PackageBundle.majorVersion] for any summaries
122 * created by this code. When making a breaking change to the summary format, 24 * created by this code. When making a breaking change to the summary format,
123 * this value should be incremented by 1 and [currentMinorVersion] should be 25 * this value should be incremented by 1 and [currentMinorVersion] should be
124 * reset to zero. 26 * reset to zero.
125 */ 27 */
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 91
190 /** 92 /**
191 * Use the dependency information in [summaryDataStore] to populate the 93 * Use the dependency information in [summaryDataStore] to populate the
192 * dependencies in the package bundle being assembled. 94 * dependencies in the package bundle being assembled.
193 */ 95 */
194 void recordDependencies(SummaryDataStore summaryDataStore) { 96 void recordDependencies(SummaryDataStore summaryDataStore) {
195 _dependencies.addAll(summaryDataStore.dependencies); 97 _dependencies.addAll(summaryDataStore.dependencies);
196 } 98 }
197 99
198 /** 100 /**
199 * Serialize the library with the given [element].
200 */
201 void serializeLibraryElement(LibraryElement element) {
202 String uri = element.source.uri.toString();
203 LibrarySerializationResult libraryResult = serializeLibrary(
204 element,
205 element.context.typeProvider,
206 element.context.analysisOptions.strongMode);
207 _linkedLibraryUris.add(uri);
208 _linkedLibraries.add(libraryResult.linked);
209 _unlinkedUnitUris.addAll(libraryResult.unitUris);
210 _unlinkedUnits.addAll(libraryResult.unlinkedUnits);
211 for (int i = 0; i < libraryResult.unitUris.length; i++) {
212 _unlinkedUnitMap[libraryResult.unitUris[i]] =
213 libraryResult.unlinkedUnits[i];
214 }
215 for (Source source in libraryResult.unitSources) {
216 _unlinkedUnitHashes?.add(_hash(source.contents.data));
217 }
218 }
219
220 /**
221 * Compute the API signature for this package bundle. 101 * Compute the API signature for this package bundle.
222 */ 102 */
223 String _computeApiSignature() { 103 String _computeApiSignature() {
224 ApiSignature apiSignature = new ApiSignature(); 104 ApiSignature apiSignature = new ApiSignature();
225 for (String unitUri in _unlinkedUnitMap.keys.toList()..sort()) { 105 for (String unitUri in _unlinkedUnitMap.keys.toList()..sort()) {
226 apiSignature.addString(unitUri); 106 apiSignature.addString(unitUri);
227 _unlinkedUnitMap[unitUri].collectApiSignature(apiSignature); 107 _unlinkedUnitMap[unitUri].collectApiSignature(apiSignature);
228 } 108 }
229 return apiSignature.toHex(); 109 return apiSignature.toHex();
230 } 110 }
231 111
232 /** 112 /**
233 * Compute a hash of the given file contents. 113 * Compute a hash of the given file contents.
234 */ 114 */
235 String _hash(String contents) { 115 String _hash(String contents) {
236 return hex.encode(md5.convert(UTF8.encode(contents)).bytes); 116 return hex.encode(md5.convert(UTF8.encode(contents)).bytes);
237 } 117 }
238 } 118 }
239
240 /**
241 * Instances of this class keep track of intermediate state during
242 * serialization of a single compilation unit.
243 */
244 class _CompilationUnitSerializer {
245 /**
246 * The [_LibrarySerializer] which is serializing the library of which
247 * [compilationUnit] is a part.
248 */
249 final _LibrarySerializer librarySerializer;
250
251 /**
252 * The [CompilationUnitElement] being serialized.
253 */
254 final CompilationUnitElement compilationUnit;
255
256 /**
257 * The ordinal index of [compilationUnit] within the library, where 0
258 * represents the defining compilation unit.
259 */
260 final int unitNum;
261
262 /**
263 * The final linked summary of the compilation unit.
264 */
265 final LinkedUnitBuilder linkedUnit = new LinkedUnitBuilder();
266
267 /**
268 * The final unlinked summary of the compilation unit.
269 */
270 final UnlinkedUnitBuilder unlinkedUnit = new UnlinkedUnitBuilder();
271
272 /**
273 * Absolute URI of the compilation unit.
274 */
275 String unitUri;
276
277 /**
278 * Map from [Element] to the index of the entry in the "references table"
279 * that refers to it.
280 */
281 final Map<Element, int> referenceMap = <Element, int>{};
282
283 /**
284 * The unlinked portion of the "references table". This is the list of
285 * objects which should be written to [UnlinkedUnit.references].
286 */
287 List<UnlinkedReferenceBuilder> unlinkedReferences;
288
289 /**
290 * The linked portion of the "references table". This is the list of
291 * objects which should be written to [LinkedUnit.references].
292 */
293 List<LinkedReferenceBuilder> linkedReferences;
294
295 /**
296 * The number of slot ids which have been assigned to this compilation unit.
297 */
298 int numSlots = 0;
299
300 /**
301 * List of closures which should be invoked at the end of serialization of a
302 * compilation unit, to produce [LinkedUnit.types].
303 */
304 final List<_SerializeTypeRef> deferredLinkedTypes = <_SerializeTypeRef>[];
305
306 /**
307 * List which should be stored in [LinkedUnit.constCycles].
308 */
309 final List<int> constCycles = <int>[];
310
311 /**
312 * Index into the "references table" representing an unresolved reference, if
313 * such an index exists. `null` if no such entry has been made in the
314 * references table yet.
315 */
316 int unresolvedReferenceIndex = null;
317
318 /**
319 * Index into the "references table" representing the "bottom" type, if such
320 * an index exists. `null` if no such entry has been made in the references
321 * table yet.
322 */
323 int bottomReferenceIndex = null;
324
325 /**
326 * If `true`, we are currently generating linked references, so new
327 * references will be not stored in [unlinkedReferences].
328 */
329 bool buildingLinkedReferences = false;
330
331 _CompilationUnitSerializer(
332 this.librarySerializer, this.compilationUnit, this.unitNum);
333
334 /**
335 * Source object for the compilation unit.
336 */
337 Source get unitSource => compilationUnit.source;
338
339 /**
340 * Add all classes, enums, typedefs, executables, and top level variables
341 * from the given compilation unit [element] to the compilation unit summary.
342 * [unitNum] indicates the ordinal position of this compilation unit in the
343 * library.
344 */
345 void addCompilationUnitElements() {
346 unlinkedReferences = <UnlinkedReferenceBuilder>[
347 new UnlinkedReferenceBuilder()
348 ];
349 linkedReferences = <LinkedReferenceBuilder>[
350 new LinkedReferenceBuilder(kind: ReferenceKind.unresolved)
351 ];
352 List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
353 for (PropertyAccessorElement accessor in compilationUnit.accessors) {
354 if (accessor.isPublic) {
355 names.add(new UnlinkedPublicNameBuilder(
356 kind: ReferenceKind.topLevelPropertyAccessor,
357 name: accessor.name,
358 numTypeParameters: accessor.typeParameters.length));
359 }
360 }
361 for (ClassElement cls in compilationUnit.types) {
362 if (cls.isPublic) {
363 names.add(new UnlinkedPublicNameBuilder(
364 kind: ReferenceKind.classOrEnum,
365 name: cls.name,
366 numTypeParameters: cls.typeParameters.length,
367 members: serializeClassStaticMembers(cls)));
368 }
369 }
370 for (ClassElement enm in compilationUnit.enums) {
371 if (enm.isPublic) {
372 names.add(new UnlinkedPublicNameBuilder(
373 kind: ReferenceKind.classOrEnum,
374 name: enm.name,
375 members: serializeClassStaticMembers(enm)));
376 }
377 }
378 for (FunctionElement function in compilationUnit.functions) {
379 if (function.isPublic) {
380 names.add(new UnlinkedPublicNameBuilder(
381 kind: ReferenceKind.topLevelFunction,
382 name: function.name,
383 numTypeParameters: function.typeParameters.length));
384 }
385 }
386 for (FunctionTypeAliasElement typedef
387 in compilationUnit.functionTypeAliases) {
388 if (typedef.isPublic) {
389 names.add(new UnlinkedPublicNameBuilder(
390 kind: ReferenceKind.typedef,
391 name: typedef.name,
392 numTypeParameters: typedef.typeParameters.length));
393 }
394 }
395 if (unitNum == 0) {
396 LibraryElement libraryElement = librarySerializer.libraryElement;
397 if (libraryElement.name.isNotEmpty) {
398 LibraryElement libraryElement = librarySerializer.libraryElement;
399 unlinkedUnit.libraryName = libraryElement.name;
400 unlinkedUnit.libraryNameOffset = libraryElement.nameOffset;
401 unlinkedUnit.libraryNameLength = libraryElement.nameLength;
402 unlinkedUnit.libraryDocumentationComment =
403 serializeDocumentation(libraryElement);
404 unlinkedUnit.libraryAnnotations = serializeAnnotations(libraryElement);
405 }
406 unlinkedUnit.publicNamespace = new UnlinkedPublicNamespaceBuilder(
407 exports: libraryElement.exports.map(serializeExportPublic).toList(),
408 parts: libraryElement.parts
409 .map((CompilationUnitElement e) => e.uri)
410 .toList(),
411 names: names);
412 unlinkedUnit.exports =
413 libraryElement.exports.map(serializeExportNonPublic).toList();
414 unlinkedUnit.imports =
415 libraryElement.imports.map(serializeImport).toList();
416 unlinkedUnit.parts = libraryElement.parts
417 .map((CompilationUnitElement e) => new UnlinkedPartBuilder(
418 uriOffset: e.uriOffset,
419 uriEnd: e.uriEnd,
420 annotations: serializeAnnotations(e)))
421 .toList();
422 } else {
423 // TODO(paulberry): we need to figure out a way to record library, part,
424 // import, and export declarations that appear in non-defining
425 // compilation units (even though such declarations are prohibited by the
426 // language), so that if the user makes code changes that cause a
427 // non-defining compilation unit to become a defining compilation unit,
428 // we can create a correct summary by simply re-linking.
429 unlinkedUnit.publicNamespace =
430 new UnlinkedPublicNamespaceBuilder(names: names);
431 }
432 unlinkedUnit.codeRange = serializeCodeRange(compilationUnit);
433 unlinkedUnit.classes = compilationUnit.types.map(serializeClass).toList();
434 unlinkedUnit.enums = compilationUnit.enums.map(serializeEnum).toList();
435 unlinkedUnit.typedefs =
436 compilationUnit.functionTypeAliases.map(serializeTypedef).toList();
437 List<UnlinkedExecutableBuilder> executables =
438 compilationUnit.functions.map(serializeExecutable).toList();
439 for (PropertyAccessorElement accessor in compilationUnit.accessors) {
440 if (!accessor.isSynthetic) {
441 executables.add(serializeExecutable(accessor));
442 }
443 }
444 unlinkedUnit.executables = executables;
445 List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
446 for (PropertyAccessorElement accessor in compilationUnit.accessors) {
447 if (accessor.isSynthetic && accessor.isGetter) {
448 PropertyInducingElement variable = accessor.variable;
449 if (variable != null) {
450 assert(!variable.isSynthetic);
451 variables.add(serializeVariable(variable));
452 }
453 }
454 }
455 unlinkedUnit.variables = variables;
456 unlinkedUnit.references = unlinkedReferences;
457 unlinkedUnit.lineStarts =
458 compilationUnit.context?.computeLineInfo(unitSource)?.lineStarts;
459 linkedUnit.references = linkedReferences;
460 unitUri = compilationUnit.source.uri.toString();
461 }
462
463 /**
464 * Create the [LinkedUnit.types] table based on deferred types that were
465 * found during [addCompilationUnitElements]. Also populate
466 * [LinkedUnit.constCycles].
467 */
468 void createLinkedInfo() {
469 buildingLinkedReferences = true;
470 linkedUnit.types = deferredLinkedTypes
471 .map((_SerializeTypeRef closure) => closure())
472 .toList();
473 linkedUnit.constCycles = constCycles;
474 buildingLinkedReferences = false;
475 }
476
477 /**
478 * Compute the appropriate De Bruijn index to represent the given type
479 * parameter [type], or return `null` if the type parameter is not in scope.
480 */
481 int findTypeParameterIndex(TypeParameterType type, Element context) {
482 int index = 0;
483 while (context != null) {
484 List<TypeParameterElement> typeParameters;
485 if (context is ClassElement) {
486 typeParameters = context.typeParameters;
487 } else if (context is FunctionTypeAliasElement) {
488 typeParameters = context.typeParameters;
489 } else if (context is ExecutableElement) {
490 typeParameters = context.typeParameters;
491 }
492 if (typeParameters != null) {
493 for (int i = 0; i < typeParameters.length; i++) {
494 TypeParameterElement param = typeParameters[i];
495 if (param == type.element) {
496 return index + typeParameters.length - i;
497 }
498 }
499 index += typeParameters.length;
500 }
501 context = context.enclosingElement;
502 }
503 return null;
504 }
505
506 /**
507 * Get the type arguments for the given [type], or `null` if the type has no
508 * type arguments.
509 *
510 * TODO(paulberry): consider adding an abstract getter to [DartType] to do
511 * this.
512 */
513 List<DartType> getTypeArguments(DartType type) {
514 if (type is InterfaceType) {
515 return type.typeArguments;
516 } else if (type is FunctionType) {
517 return type.typeArguments;
518 } else {
519 return null;
520 }
521 }
522
523 /**
524 * Serialize annotations from the given [element]. If [element] has no
525 * annotations, the empty list is returned.
526 */
527 List<UnlinkedConstBuilder> serializeAnnotations(Element element) {
528 if (element.metadata.isEmpty) {
529 return const <UnlinkedConstBuilder>[];
530 }
531 return element.metadata.map((ElementAnnotation a) {
532 _ConstExprSerializer serializer =
533 new _ConstExprSerializer(this, element, null, null);
534 serializer
535 .serializeAnnotation((a as ElementAnnotationImpl).annotationAst);
536 return serializer.toBuilder();
537 }).toList();
538 }
539
540 /**
541 * Return the index of the entry in the references table
542 * ([LinkedLibrary.references]) used for the "bottom" type. A new entry is
543 * added to the table if necessary to satisfy the request.
544 */
545 int serializeBottomReference() {
546 if (bottomReferenceIndex == null) {
547 // References to the "bottom" type are always implicit, since there is no
548 // way to explicitly refer to the "bottom" type. Therefore they should
549 // be stored only in the linked references table.
550 bottomReferenceIndex = linkedReferences.length;
551 linkedReferences.add(new LinkedReferenceBuilder(
552 name: '*bottom*', kind: ReferenceKind.classOrEnum));
553 }
554 return bottomReferenceIndex;
555 }
556
557 /**
558 * Serialize the given [classElement], creating an [UnlinkedClass].
559 */
560 UnlinkedClassBuilder serializeClass(ClassElement classElement) {
561 UnlinkedClassBuilder b = new UnlinkedClassBuilder();
562 b.name = classElement.name;
563 b.nameOffset = classElement.nameOffset;
564 b.typeParameters =
565 classElement.typeParameters.map(serializeTypeParam).toList();
566 if (classElement.supertype == null) {
567 b.hasNoSupertype = true;
568 } else if (!classElement.supertype.isObject) {
569 b.supertype = serializeTypeRef(classElement.supertype, classElement);
570 }
571 b.mixins = classElement.mixins
572 .map((InterfaceType t) => serializeTypeRef(t, classElement))
573 .toList();
574 b.interfaces = classElement.interfaces
575 .map((InterfaceType t) => serializeTypeRef(t, classElement))
576 .toList();
577 List<UnlinkedVariableBuilder> fields = <UnlinkedVariableBuilder>[];
578 List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
579 for (ConstructorElement executable in classElement.constructors) {
580 if (!executable.isSynthetic) {
581 executables.add(serializeExecutable(executable));
582 }
583 }
584 for (MethodElement executable in classElement.methods) {
585 executables.add(serializeExecutable(executable));
586 }
587 for (PropertyAccessorElement accessor in classElement.accessors) {
588 if (!accessor.isSynthetic) {
589 executables.add(serializeExecutable(accessor));
590 } else if (accessor.isGetter) {
591 PropertyInducingElement field = accessor.variable;
592 if (field != null && !field.isSynthetic) {
593 fields.add(serializeVariable(field));
594 }
595 }
596 }
597 b.fields = fields;
598 b.executables = executables;
599 b.isAbstract = classElement.isAbstract;
600 b.isMixinApplication = classElement.isMixinApplication;
601 b.documentationComment = serializeDocumentation(classElement);
602 b.annotations = serializeAnnotations(classElement);
603 b.codeRange = serializeCodeRange(classElement);
604 return b;
605 }
606
607 /**
608 * If [cls] is a class, return the list of its static members - static
609 * constant fields, static methods and constructors. Otherwise return `null`.
610 */
611 List<UnlinkedPublicNameBuilder> serializeClassStaticMembers(
612 ClassElement cls) {
613 if (cls.isMixinApplication) {
614 // Mixin application members can't be determined directly from the AST so
615 // we can't store them in UnlinkedPublicName.
616 // TODO(paulberry): find somewhere else to store them.
617 return null;
618 }
619 if (cls.kind == ElementKind.CLASS) {
620 List<UnlinkedPublicNameBuilder> bs = <UnlinkedPublicNameBuilder>[];
621 for (MethodElement method in cls.methods) {
622 if (method.isStatic && method.isPublic) {
623 // TODO(paulberry): should numTypeParameters include class params?
624 bs.add(new UnlinkedPublicNameBuilder(
625 name: method.name,
626 kind: ReferenceKind.method,
627 numTypeParameters: method.typeParameters.length));
628 }
629 }
630 for (PropertyAccessorElement accessor in cls.accessors) {
631 if (accessor.isStatic && accessor.isGetter && accessor.isPublic) {
632 // TODO(paulberry): should numTypeParameters include class params?
633 bs.add(new UnlinkedPublicNameBuilder(
634 name: accessor.name, kind: ReferenceKind.propertyAccessor));
635 }
636 }
637 for (ConstructorElement constructor in cls.constructors) {
638 if (constructor.isPublic && constructor.name.isNotEmpty) {
639 // TODO(paulberry): should numTypeParameters include class params?
640 bs.add(new UnlinkedPublicNameBuilder(
641 name: constructor.name,
642 kind: ReferenceKind.constructor,
643 numTypeParameters: 0));
644 }
645 }
646 return bs;
647 }
648 return null;
649 }
650
651 CodeRangeBuilder serializeCodeRange(Element element) {
652 if (element is ElementImpl && element.codeOffset != null) {
653 return new CodeRangeBuilder(
654 offset: element.codeOffset, length: element.codeLength);
655 }
656 return null;
657 }
658
659 /**
660 * Serialize the given [combinator] into an [UnlinkedCombinator].
661 */
662 UnlinkedCombinatorBuilder serializeCombinator(
663 NamespaceCombinator combinator) {
664 UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
665 if (combinator is ShowElementCombinator) {
666 b.shows = combinator.shownNames;
667 b.offset = combinator.offset;
668 b.end = combinator.end;
669 } else if (combinator is HideElementCombinator) {
670 b.hides = combinator.hiddenNames;
671 }
672 return b;
673 }
674
675 /**
676 * Serialize the given [expression], creating an [UnlinkedConstBuilder].
677 */
678 UnlinkedConstBuilder serializeConstExpr(Element context,
679 ExecutableElement executableContext, Expression expression,
680 [Set<String> constructorParameterNames]) {
681 _ConstExprSerializer serializer = new _ConstExprSerializer(
682 this, context, executableContext, constructorParameterNames);
683 serializer.serialize(expression);
684 return serializer.toBuilder();
685 }
686
687 /**
688 * Serialize documentation from the given [element], creating an
689 * [UnlinkedDocumentationComment].
690 *
691 * If [element] has no documentation, `null` is returned.
692 */
693 UnlinkedDocumentationCommentBuilder serializeDocumentation(Element element) {
694 if (element.documentationComment == null) {
695 return null;
696 }
697 return new UnlinkedDocumentationCommentBuilder(
698 text: element.documentationComment);
699 }
700
701 /**
702 * Serialize the given [enumElement], creating an [UnlinkedEnum].
703 */
704 UnlinkedEnumBuilder serializeEnum(ClassElement enumElement) {
705 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
706 b.name = enumElement.name;
707 b.nameOffset = enumElement.nameOffset;
708 List<UnlinkedEnumValueBuilder> values = <UnlinkedEnumValueBuilder>[];
709 for (FieldElement field in enumElement.fields) {
710 if (field.isConst && field.type.element == enumElement) {
711 values.add(new UnlinkedEnumValueBuilder(
712 name: field.name,
713 nameOffset: field.nameOffset,
714 documentationComment: serializeDocumentation(field)));
715 }
716 }
717 b.values = values;
718 b.documentationComment = serializeDocumentation(enumElement);
719 b.annotations = serializeAnnotations(enumElement);
720 b.codeRange = serializeCodeRange(enumElement);
721 return b;
722 }
723
724 /**
725 * Serialize the given [executableElement], creating an [UnlinkedExecutable].
726 */
727 UnlinkedExecutableBuilder serializeExecutable(
728 ExecutableElement executableElement) {
729 UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
730 b.name = executableElement.name;
731 b.nameOffset = executableElement.nameOffset;
732 if (executableElement is ConstructorElement) {
733 if (executableElement.name.isNotEmpty) {
734 b.nameEnd = executableElement.nameEnd;
735 b.periodOffset = executableElement.periodOffset;
736 }
737 } else {
738 if (!executableElement.hasImplicitReturnType) {
739 b.returnType = serializeTypeRef(
740 executableElement.type.returnType, executableElement);
741 } else if (!executableElement.isStatic) {
742 b.inferredReturnTypeSlot =
743 storeInferredType(executableElement.returnType, executableElement);
744 }
745 }
746 b.typeParameters =
747 executableElement.typeParameters.map(serializeTypeParam).toList();
748 b.parameters =
749 executableElement.type.parameters.map(serializeParam).toList();
750 if (executableElement is PropertyAccessorElement) {
751 if (executableElement.isGetter) {
752 b.kind = UnlinkedExecutableKind.getter;
753 } else {
754 b.kind = UnlinkedExecutableKind.setter;
755 }
756 } else if (executableElement is ConstructorElementImpl) {
757 b.kind = UnlinkedExecutableKind.constructor;
758 b.isConst = executableElement.isConst;
759 b.isFactory = executableElement.isFactory;
760 ConstructorElement redirectedConstructor =
761 executableElement.redirectedConstructor;
762 if (redirectedConstructor != null) {
763 b.isRedirectedConstructor = true;
764 if (executableElement.isFactory) {
765 InterfaceType returnType = redirectedConstructor is ConstructorMember
766 ? redirectedConstructor.definingType
767 : redirectedConstructor.enclosingElement.type;
768 EntityRefBuilder typeRef =
769 serializeTypeRef(returnType, executableElement);
770 if (redirectedConstructor.name.isNotEmpty) {
771 String name = redirectedConstructor.name;
772 int typeId = typeRef.reference;
773 LinkedReference typeLinkedRef = linkedReferences[typeId];
774 int refId = serializeUnlinkedReference(
775 name, ReferenceKind.constructor,
776 unit: typeLinkedRef.unit, prefixReference: typeId);
777 b.redirectedConstructor = new EntityRefBuilder(
778 reference: refId, typeArguments: typeRef.typeArguments);
779 } else {
780 b.redirectedConstructor = typeRef;
781 }
782 } else {
783 b.redirectedConstructorName = redirectedConstructor.name;
784 }
785 }
786 if (executableElement.isConst) {
787 b.constCycleSlot = storeConstCycle(!executableElement.isCycleFree);
788 if (executableElement.constantInitializers != null) {
789 Set<String> constructorParameterNames =
790 executableElement.parameters.map((p) => p.name).toSet();
791 b.constantInitializers = executableElement.constantInitializers
792 .map((ConstructorInitializer initializer) =>
793 serializeConstructorInitializer(
794 initializer,
795 (expr) => serializeConstExpr(executableElement,
796 executableElement, expr, constructorParameterNames)))
797 .toList();
798 }
799 }
800 } else {
801 b.kind = UnlinkedExecutableKind.functionOrMethod;
802 }
803 b.isAbstract = executableElement.isAbstract;
804 b.isAsynchronous = executableElement.isAsynchronous;
805 b.isGenerator = executableElement.isGenerator;
806 b.isStatic = executableElement.isStatic &&
807 executableElement.enclosingElement is ClassElement;
808 b.isExternal = executableElement.isExternal;
809 b.documentationComment = serializeDocumentation(executableElement);
810 b.annotations = serializeAnnotations(executableElement);
811 b.codeRange = serializeCodeRange(executableElement);
812 if (executableElement is FunctionElement) {
813 SourceRange visibleRange = executableElement.visibleRange;
814 if (visibleRange != null) {
815 b.visibleOffset = visibleRange.offset;
816 b.visibleLength = visibleRange.length;
817 }
818 }
819 b.localFunctions =
820 executableElement.functions.map(serializeExecutable).toList();
821 b.localLabels = executableElement.labels.map(serializeLabel).toList();
822 b.localVariables =
823 executableElement.localVariables.map(serializeVariable).toList();
824 return b;
825 }
826
827 /**
828 * Serialize the given [exportElement] into an [UnlinkedExportNonPublic].
829 */
830 UnlinkedExportNonPublicBuilder serializeExportNonPublic(
831 ExportElement exportElement) {
832 UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder();
833 b.offset = exportElement.nameOffset;
834 b.uriOffset = exportElement.uriOffset;
835 b.uriEnd = exportElement.uriEnd;
836 b.annotations = serializeAnnotations(exportElement);
837 return b;
838 }
839
840 /**
841 * Serialize the given [exportElement] into an [UnlinkedExportPublic].
842 */
843 UnlinkedExportPublicBuilder serializeExportPublic(
844 ExportElement exportElement) {
845 UnlinkedExportPublicBuilder b = new UnlinkedExportPublicBuilder();
846 b.uri = exportElement.uri;
847 b.combinators = exportElement.combinators.map(serializeCombinator).toList();
848 return b;
849 }
850
851 /**
852 * Serialize the given [importElement] yielding an [UnlinkedImportBuilder].
853 * Also, add linked information about it to the [linkedImports] list.
854 */
855 UnlinkedImportBuilder serializeImport(ImportElement importElement) {
856 UnlinkedImportBuilder b = new UnlinkedImportBuilder();
857 b.annotations = serializeAnnotations(importElement);
858 b.isDeferred = importElement.isDeferred;
859 b.combinators = importElement.combinators.map(serializeCombinator).toList();
860 if (importElement.prefix != null) {
861 b.prefixReference = serializePrefix(importElement.prefix);
862 b.prefixOffset = importElement.prefix.nameOffset;
863 }
864 if (importElement.isSynthetic) {
865 b.isImplicit = true;
866 } else {
867 b.offset = importElement.nameOffset;
868 b.uri = importElement.uri;
869 b.uriOffset = importElement.uriOffset;
870 b.uriEnd = importElement.uriEnd;
871 }
872 return b;
873 }
874
875 /**
876 * Serialize the given [label], creating an [UnlinkedLabelBuilder].
877 */
878 UnlinkedLabelBuilder serializeLabel(LabelElement label) {
879 LabelElementImpl labelImpl = label as LabelElementImpl;
880 UnlinkedLabelBuilder b = new UnlinkedLabelBuilder();
881 b.name = labelImpl.name;
882 b.nameOffset = labelImpl.nameOffset;
883 b.isOnSwitchMember = labelImpl.isOnSwitchMember;
884 b.isOnSwitchStatement = labelImpl.isOnSwitchStatement;
885 return b;
886 }
887
888 /**
889 * Serialize the given [parameter] into an [UnlinkedParam].
890 */
891 UnlinkedParamBuilder serializeParam(ParameterElement parameter,
892 [Element context]) {
893 context ??= parameter;
894 UnlinkedParamBuilder b = new UnlinkedParamBuilder();
895 b.name = parameter.name;
896 b.nameOffset = parameter.nameOffset >= 0 ? parameter.nameOffset : 0;
897 switch (parameter.parameterKind) {
898 case ParameterKind.REQUIRED:
899 b.kind = UnlinkedParamKind.required;
900 break;
901 case ParameterKind.POSITIONAL:
902 b.kind = UnlinkedParamKind.positional;
903 break;
904 case ParameterKind.NAMED:
905 b.kind = UnlinkedParamKind.named;
906 break;
907 }
908 b.annotations = serializeAnnotations(parameter);
909 b.codeRange = serializeCodeRange(parameter);
910 b.isInitializingFormal = parameter.isInitializingFormal;
911 DartType type = parameter.type;
912 if (parameter.hasImplicitType) {
913 Element contextParent = context.enclosingElement;
914 if (!parameter.isInitializingFormal &&
915 contextParent is ExecutableElement &&
916 !contextParent.isStatic &&
917 contextParent is! ConstructorElement) {
918 b.inferredTypeSlot = storeInferredType(type, context);
919 }
920 } else {
921 if (type is FunctionType && type.element.isSynthetic) {
922 b.isFunctionTyped = true;
923 b.type = serializeTypeRef(type.returnType, parameter);
924 b.parameters = type.parameters
925 .map((parameter) => serializeParam(parameter, context))
926 .toList();
927 } else {
928 b.type = serializeTypeRef(type, context);
929 }
930 }
931 // TODO(scheglov) VariableMember.initializer is not implemented
932 if (parameter is! VariableMember && parameter.initializer != null) {
933 b.initializer = serializeExecutable(parameter.initializer);
934 }
935 if (parameter is ConstVariableElement) {
936 ConstVariableElement constParameter = parameter as ConstVariableElement;
937 Expression initializer = constParameter.constantInitializer;
938 if (initializer != null) {
939 b.initializer?.bodyExpr = serializeConstExpr(
940 parameter,
941 parameter.getAncestor((Element e) => e is ExecutableElement),
942 initializer);
943 b.defaultValueCode = parameter.defaultValueCode;
944 }
945 }
946 {
947 SourceRange visibleRange = parameter.visibleRange;
948 if (visibleRange != null) {
949 b.visibleOffset = visibleRange.offset;
950 b.visibleLength = visibleRange.length;
951 }
952 }
953 return b;
954 }
955
956 /**
957 * Serialize the given [prefix] into an index into the references table.
958 */
959 int serializePrefix(PrefixElement element) {
960 return referenceMap.putIfAbsent(element,
961 () => serializeUnlinkedReference(element.name, ReferenceKind.prefix));
962 }
963
964 /**
965 * Compute the reference index which should be stored in a [EntityRef].
966 */
967 int serializeReferenceForType(DartType type) {
968 Element element = type.element;
969 LibraryElement dependentLibrary = element?.library;
970 if (dependentLibrary == null) {
971 if (type.isBottom) {
972 // References to the "bottom" type are always implicit, since there is
973 // no way to explicitly refer to the "bottom" type. Therefore they
974 // should always be linked.
975 assert(buildingLinkedReferences);
976 return serializeBottomReference();
977 }
978 assert(type.isDynamic || type.isVoid);
979 if (type is UndefinedTypeImpl) {
980 return serializeUnresolvedReference();
981 }
982 // Note: for a type which is truly `dynamic` or `void`, fall through to
983 // use [_getElementReferenceId].
984 }
985 return _getElementReferenceId(element);
986 }
987
988 /**
989 * Serialize the given [typedefElement], creating an [UnlinkedTypedef].
990 */
991 UnlinkedTypedefBuilder serializeTypedef(
992 FunctionTypeAliasElement typedefElement) {
993 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
994 b.name = typedefElement.name;
995 b.nameOffset = typedefElement.nameOffset;
996 b.typeParameters =
997 typedefElement.typeParameters.map(serializeTypeParam).toList();
998 b.returnType = serializeTypeRef(typedefElement.returnType, typedefElement);
999 b.parameters = typedefElement.parameters.map(serializeParam).toList();
1000 b.documentationComment = serializeDocumentation(typedefElement);
1001 b.annotations = serializeAnnotations(typedefElement);
1002 b.codeRange = serializeCodeRange(typedefElement);
1003 return b;
1004 }
1005
1006 /**
1007 * Serialize the given [typeParameter] into an [UnlinkedTypeParam].
1008 */
1009 UnlinkedTypeParamBuilder serializeTypeParam(
1010 TypeParameterElement typeParameter) {
1011 UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
1012 b.name = typeParameter.name;
1013 b.nameOffset = typeParameter.nameOffset;
1014 if (typeParameter.bound != null) {
1015 b.bound = serializeTypeRef(typeParameter.bound, typeParameter);
1016 }
1017 b.annotations = serializeAnnotations(typeParameter);
1018 b.codeRange = serializeCodeRange(typeParameter);
1019 return b;
1020 }
1021
1022 /**
1023 * Serialize the given [type] into a [EntityRef]. If [slot] is provided,
1024 * it should be included in the [EntityRef].
1025 *
1026 * [context] is the element within which the [EntityRef] will be
1027 * interpreted; this is used to serialize type parameters.
1028 */
1029 EntityRefBuilder serializeTypeRef(DartType type, Element context,
1030 {int slot}) {
1031 if (slot != null) {
1032 assert(buildingLinkedReferences);
1033 }
1034 EntityRefBuilder b = new EntityRefBuilder(slot: slot);
1035 Element typeElement = type.element;
1036 if (type is TypeParameterType) {
1037 int typeParameterIndex = findTypeParameterIndex(type, context);
1038 if (typeParameterIndex != null) {
1039 b.paramReference = typeParameterIndex;
1040 } else {
1041 // Out-of-scope type parameters only occur in circumstances where they
1042 // are irrelevant (i.e. when a type parameter is unused). So we can
1043 // safely convert them to `dynamic`.
1044 b.reference = serializeReferenceForType(DynamicTypeImpl.instance);
1045 }
1046 } else if (type is FunctionType &&
1047 typeElement is FunctionElement &&
1048 typeElement.enclosingElement == null) {
1049 b.syntheticReturnType =
1050 serializeTypeRef(typeElement.returnType, typeElement);
1051 b.syntheticParams = typeElement.parameters
1052 .map((ParameterElement param) => serializeParam(param, context))
1053 .toList();
1054 } else {
1055 if (type is FunctionType &&
1056 typeElement.enclosingElement is ParameterElement) {
1057 // Code cannot refer to function types implicitly defined by parameters
1058 // directly, so if we get here, we must be serializing a linked
1059 // reference from type inference.
1060 assert(buildingLinkedReferences);
1061 ParameterElement parameterElement = typeElement.enclosingElement;
1062 while (true) {
1063 Element parent = parameterElement.enclosingElement;
1064 if (parent is ParameterElement) {
1065 // Function-typed parameter inside a function-typed parameter.
1066 b.implicitFunctionTypeIndices
1067 .insert(0, parent.parameters.indexOf(parameterElement));
1068 parameterElement = parent;
1069 continue;
1070 } else if (parent is FunctionTypedElement) {
1071 b.implicitFunctionTypeIndices
1072 .insert(0, parent.parameters.indexOf(parameterElement));
1073 // Function-typed parameter inside a top level function, method, or
1074 // typedef.
1075 b.reference = _getElementReferenceId(parent);
1076 break;
1077 } else {
1078 throw new StateError(
1079 'Unexpected element enclosing parameter: ${parent.runtimeType}') ;
1080 }
1081 }
1082 } else {
1083 b.reference = serializeReferenceForType(type);
1084 }
1085 List<DartType> typeArguments = getTypeArguments(type);
1086 if (typeArguments != null) {
1087 b.typeArguments = typeArguments
1088 .map((typeArgument) => serializeTypeRef(typeArgument, context))
1089 .toList();
1090 }
1091 }
1092 return b;
1093 }
1094
1095 /**
1096 * Create a new entry in the references table ([UnlinkedUnit.references]
1097 * and [LinkedUnit.references]) representing an entity having the given
1098 * [name] and [kind]. If [unit] is given, it is the index of the compilation
1099 * unit containing the entity being referred to. If [prefixReference] is
1100 * given, it indicates the entry in the references table for the prefix.
1101 */
1102 int serializeUnlinkedReference(String name, ReferenceKind kind,
1103 {int unit: 0, int prefixReference: 0}) {
1104 assert(unlinkedReferences.length == linkedReferences.length);
1105 int index = unlinkedReferences.length;
1106 unlinkedReferences.add(new UnlinkedReferenceBuilder(
1107 name: name, prefixReference: prefixReference));
1108 linkedReferences.add(new LinkedReferenceBuilder(kind: kind, unit: unit));
1109 return index;
1110 }
1111
1112 /**
1113 * Return the index of the entry in the references table
1114 * ([UnlinkedLibrary.references] and [LinkedLibrary.references]) used for
1115 * unresolved references. A new entry is added to the table if necessary to
1116 * satisfy the request.
1117 */
1118 int serializeUnresolvedReference() {
1119 // TODO(paulberry): in order for relinking to work, we need to record the
1120 // name and prefix of the unresolved symbol. This is not (yet) encoded in
1121 // the element model. For the moment we use a name that can't possibly
1122 // ever exist.
1123 if (unresolvedReferenceIndex == null) {
1124 unresolvedReferenceIndex =
1125 serializeUnlinkedReference('*unresolved*', ReferenceKind.unresolved);
1126 }
1127 return unresolvedReferenceIndex;
1128 }
1129
1130 /**
1131 * Serialize the given [variable], creating an [UnlinkedVariable].
1132 */
1133 UnlinkedVariableBuilder serializeVariable(VariableElement variable) {
1134 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
1135 b.name = variable.name;
1136 b.nameOffset = variable.nameOffset;
1137 if (!variable.hasImplicitType) {
1138 b.type = serializeTypeRef(variable.type, variable);
1139 }
1140 b.isStatic = variable.isStatic && variable.enclosingElement is ClassElement;
1141 b.isFinal = variable.isFinal;
1142 b.isConst = variable.isConst;
1143 b.documentationComment = serializeDocumentation(variable);
1144 b.annotations = serializeAnnotations(variable);
1145 // TODO(scheglov) VariableMember.initializer is not implemented
1146 if (variable is! VariableMember && variable.initializer != null) {
1147 b.initializer = serializeExecutable(variable.initializer);
1148 }
1149 if (variable is ConstVariableElement) {
1150 ConstVariableElement constVariable = variable as ConstVariableElement;
1151 Expression initializer = constVariable.constantInitializer;
1152 if (initializer != null) {
1153 b.initializer?.bodyExpr =
1154 serializeConstExpr(variable, variable.initializer, initializer);
1155 }
1156 }
1157 if (variable is PropertyInducingElement) {
1158 if (b.isFinal || b.isConst) {
1159 b.propagatedTypeSlot =
1160 storeLinkedType(variable.propagatedType, variable);
1161 } else {
1162 // Variable is not propagable.
1163 assert(variable.propagatedType == null);
1164 }
1165 }
1166 if (variable.hasImplicitType &&
1167 (variable.initializer != null || !variable.isStatic)) {
1168 b.inferredTypeSlot = storeInferredType(variable.type, variable);
1169 }
1170 b.codeRange = serializeCodeRange(variable);
1171 if (variable is LocalVariableElement) {
1172 SourceRange visibleRange = variable.visibleRange;
1173 if (visibleRange != null) {
1174 b.visibleOffset = visibleRange.offset;
1175 b.visibleLength = visibleRange.length;
1176 }
1177 }
1178 return b;
1179 }
1180
1181 /**
1182 * Create a new slot id and return it. If [hasCycle] is `true`, arrange for
1183 * the slot id to be included in [LinkedUnit.constCycles].
1184 */
1185 int storeConstCycle(bool hasCycle) {
1186 int slot = ++numSlots;
1187 if (hasCycle) {
1188 constCycles.add(slot);
1189 }
1190 return slot;
1191 }
1192
1193 /**
1194 * Create a slot id for the given [type] (which is an inferred type). If
1195 * [type] is not `dynamic`, it is stored in [linkedTypes] so that once the
1196 * compilation unit has been fully visited, it will be serialized into
1197 * [LinkedUnit.types].
1198 *
1199 * [context] is the element within which the slot id will appear; this is
1200 * used to serialize type parameters.
1201 */
1202 int storeInferredType(DartType type, Element context) {
1203 return storeLinkedType(type.isDynamic ? null : type, context);
1204 }
1205
1206 /**
1207 * Create a slot id for the given [type] (which may be either a propagated
1208 * type or an inferred type). If [type] is not `null`, it is stored in
1209 * [linkedTypes] so that once the compilation unit has been fully visited,
1210 * it will be serialized to [LinkedUnit.types].
1211 *
1212 * [context] is the element within which the slot id will appear; this is
1213 * used to serialize type parameters.
1214 */
1215 int storeLinkedType(DartType type, Element context) {
1216 int slot = ++numSlots;
1217 if (type != null) {
1218 deferredLinkedTypes
1219 .add(() => serializeTypeRef(type, context, slot: slot));
1220 }
1221 return slot;
1222 }
1223
1224 int _getElementReferenceId(Element element) {
1225 return referenceMap.putIfAbsent(element, () {
1226 LibraryElement dependentLibrary = librarySerializer.libraryElement;
1227 int unit = 0;
1228 Element enclosingElement;
1229 if (element != null) {
1230 enclosingElement = element.enclosingElement;
1231 if (enclosingElement is CompilationUnitElement) {
1232 dependentLibrary = enclosingElement.library;
1233 unit = dependentLibrary.units.indexOf(enclosingElement);
1234 assert(unit != -1);
1235 }
1236 }
1237 ReferenceKind kind = _getReferenceKind(element);
1238 String name = element == null ? 'void' : element.name;
1239 int index;
1240 LinkedReferenceBuilder linkedReference;
1241 if (buildingLinkedReferences) {
1242 linkedReference =
1243 new LinkedReferenceBuilder(kind: kind, unit: unit, name: name);
1244 if (enclosingElement != null &&
1245 enclosingElement is! CompilationUnitElement) {
1246 linkedReference.containingReference =
1247 _getElementReferenceId(enclosingElement);
1248 if (enclosingElement is ClassElement) {
1249 // Nothing to do.
1250 } else if (enclosingElement is ExecutableElement) {
1251 if (element is FunctionElement) {
1252 assert(enclosingElement.functions.contains(element));
1253 linkedReference.localIndex =
1254 enclosingElement.functions.indexOf(element);
1255 } else if (element is LocalVariableElement) {
1256 assert(enclosingElement.localVariables.contains(element));
1257 linkedReference.localIndex =
1258 enclosingElement.localVariables.indexOf(element);
1259 } else {
1260 throw new StateError(
1261 'Unexpected enclosed element type: ${element.runtimeType}');
1262 }
1263 } else if (enclosingElement is VariableElement) {
1264 assert(identical(enclosingElement.initializer, element));
1265 } else {
1266 throw new StateError(
1267 'Unexpected enclosing element type: ${enclosingElement.runtimeTy pe}');
1268 }
1269 }
1270 index = linkedReferences.length;
1271 linkedReferences.add(linkedReference);
1272 } else {
1273 assert(unlinkedReferences.length == linkedReferences.length);
1274 int prefixReference = 0;
1275 Element enclosing = element?.enclosingElement;
1276 if (enclosing == null || enclosing is CompilationUnitElement) {
1277 // Figure out a prefix that may be used to refer to the given element.
1278 // TODO(paulberry): to avoid subtle relinking inconsistencies we
1279 // should use the actual prefix from the AST (a given type may be
1280 // reachable via multiple prefixes), but sadly, this information is
1281 // not recorded in the element model.
1282 PrefixElement prefix = librarySerializer.prefixMap[element];
1283 if (prefix != null) {
1284 prefixReference = serializePrefix(prefix);
1285 }
1286 } else {
1287 prefixReference = _getElementReferenceId(enclosing);
1288 }
1289 index = serializeUnlinkedReference(name, kind,
1290 prefixReference: prefixReference, unit: unit);
1291 linkedReference = linkedReferences[index];
1292 }
1293 linkedReference.dependency =
1294 librarySerializer.serializeDependency(dependentLibrary);
1295 if (element is TypeParameterizedElement) {
1296 linkedReference.numTypeParameters += element.typeParameters.length;
1297 }
1298 return index;
1299 });
1300 }
1301 }
1302
1303 /**
1304 * Instances of this class keep track of intermediate state during
1305 * serialization of a single constant [Expression].
1306 */
1307 class _ConstExprSerializer extends AbstractConstExprSerializer {
1308 final _CompilationUnitSerializer serializer;
1309 final Element context;
1310 final ExecutableElement executableContext;
1311
1312 /**
1313 * If a constructor initializer expression is being serialized, the names of
1314 * the constructor parameters. Otherwise `null`.
1315 */
1316 final Set<String> constructorParameterNames;
1317
1318 _ConstExprSerializer(this.serializer, this.context, this.executableContext,
1319 this.constructorParameterNames);
1320
1321 @override
1322 bool isParameterName(String name) {
1323 return constructorParameterNames?.contains(name) ?? false;
1324 }
1325
1326 @override
1327 void serializeAnnotation(Annotation annotation) {
1328 if (annotation.arguments == null) {
1329 assert(annotation.constructorName == null);
1330 serialize(annotation.name);
1331 } else {
1332 Identifier name = annotation.name;
1333 Element nameElement = name.staticElement;
1334 EntityRefBuilder constructor;
1335 if (nameElement is ConstructorElement && name is PrefixedIdentifier) {
1336 assert(annotation.constructorName == null);
1337 constructor = serializeConstructorRef(
1338 nameElement.returnType, name.prefix, null, name.identifier);
1339 } else if (nameElement is TypeDefiningElement) {
1340 constructor = serializeConstructorRef(nameElement.type, annotation.name,
1341 null, annotation.constructorName);
1342 } else if (nameElement == null) {
1343 // Unresolved annotation.
1344 if (name is PrefixedIdentifier && annotation.constructorName == null) {
1345 constructor =
1346 serializeConstructorRef(null, name.prefix, null, name.identifier);
1347 } else {
1348 constructor = serializeConstructorRef(
1349 null, annotation.name, null, annotation.constructorName);
1350 }
1351 } else {
1352 throw new StateError('Unexpected annotation nameElement type:'
1353 ' ${nameElement.runtimeType}');
1354 }
1355 serializeInstanceCreation(constructor, annotation.arguments);
1356 }
1357 }
1358
1359 @override
1360 EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName,
1361 TypeArgumentList typeArguments, SimpleIdentifier name) {
1362 EntityRefBuilder typeRef = serializeType(type, typeName, typeArguments);
1363 if (name == null) {
1364 return typeRef;
1365 } else {
1366 LinkedReference typeLinkedRef =
1367 serializer.linkedReferences[typeRef.reference];
1368 int refId = serializer.serializeUnlinkedReference(
1369 name.name,
1370 name.staticElement != null
1371 ? ReferenceKind.constructor
1372 : ReferenceKind.unresolved,
1373 prefixReference: typeRef.reference,
1374 unit: typeLinkedRef.unit);
1375 return new EntityRefBuilder(
1376 reference: refId, typeArguments: typeRef.typeArguments);
1377 }
1378 }
1379
1380 @override
1381 List<int> serializeFunctionExpression(FunctionExpression functionExpression) {
1382 if (executableContext == null) {
1383 return null;
1384 }
1385 ExecutableElement functionElement = functionExpression.element;
1386 // TOOD(paulberry): handle the situation where [functionExpression] is not
1387 // an immediate child of [executableContext].
1388 assert(functionElement.enclosingElement == executableContext);
1389 int popCount = 0;
1390 int localIndex = executableContext.functions.indexOf(functionElement);
1391 assert(localIndex != -1);
1392 return <int>[popCount, localIndex];
1393 }
1394
1395 EntityRefBuilder serializeIdentifier(Identifier identifier,
1396 {int prefixReference: 0}) {
1397 if (identifier is SimpleIdentifier) {
1398 Element element = identifier.staticElement;
1399 if (element is TypeParameterElement) {
1400 int typeParameterIndex =
1401 serializer.findTypeParameterIndex(element.type, context);
1402 return new EntityRefBuilder(paramReference: typeParameterIndex);
1403 } else if (_isPrelinkResolvableElement(element)) {
1404 int ref = serializer._getElementReferenceId(element);
1405 return new EntityRefBuilder(reference: ref);
1406 } else {
1407 int ref = serializer.serializeUnlinkedReference(
1408 identifier.name, ReferenceKind.unresolved);
1409 return new EntityRefBuilder(reference: ref);
1410 }
1411 } else if (identifier is PrefixedIdentifier) {
1412 Element element = identifier.staticElement;
1413 if (_isPrelinkResolvableElement(element)) {
1414 int ref = serializer._getElementReferenceId(element);
1415 return new EntityRefBuilder(reference: ref);
1416 } else {
1417 int prefixRef = serializeIdentifier(identifier.prefix).reference;
1418 int ref = serializer.serializeUnlinkedReference(
1419 identifier.identifier.name, ReferenceKind.unresolved,
1420 prefixReference: prefixRef);
1421 return new EntityRefBuilder(reference: ref);
1422 }
1423 } else {
1424 throw new StateError(
1425 'Unexpected identifier type: ${identifier.runtimeType}');
1426 }
1427 }
1428
1429 @override
1430 EntityRefBuilder serializeIdentifierSequence(Expression expr) {
1431 if (expr is Identifier) {
1432 return serializeIdentifier(expr);
1433 }
1434 if (expr is PropertyAccess) {
1435 Element element = expr.propertyName.staticElement;
1436 if (_isPrelinkResolvableElement(element)) {
1437 int ref = serializer._getElementReferenceId(element);
1438 return new EntityRefBuilder(reference: ref);
1439 } else {
1440 int targetRef = serializeIdentifierSequence(expr.target).reference;
1441 int ref = serializer.serializeUnlinkedReference(
1442 expr.propertyName.name, ReferenceKind.unresolved,
1443 prefixReference: targetRef);
1444 return new EntityRefBuilder(reference: ref);
1445 }
1446 } else {
1447 throw new StateError('Unexpected node type: ${expr.runtimeType}');
1448 }
1449 }
1450
1451 @override
1452 EntityRefBuilder serializeType(
1453 DartType type, Identifier name, TypeArgumentList arguments) {
1454 if (name != null) {
1455 if (type == null || type.isUndefined) {
1456 return serializeIdentifier(name);
1457 }
1458 }
1459 DartType typeOrDynamic = type ?? DynamicTypeImpl.instance;
1460 return serializer.serializeTypeRef(typeOrDynamic, context);
1461 }
1462
1463 /**
1464 * Return `true` if the given [element] can be resolved at prelink step.
1465 */
1466 static bool _isPrelinkResolvableElement(Element element) {
1467 if (element == null) {
1468 return false;
1469 }
1470 if (element == DynamicTypeImpl.instance.element) {
1471 return true;
1472 }
1473 if (element is PrefixElement) {
1474 return true;
1475 }
1476 Element enclosingElement = element.enclosingElement;
1477 if (enclosingElement is CompilationUnitElement) {
1478 return true;
1479 }
1480 if (enclosingElement is ClassElement) {
1481 return element is ConstructorElement ||
1482 element is ClassMemberElement && element.isStatic ||
1483 element is PropertyAccessorElement && element.isStatic;
1484 }
1485 return false;
1486 }
1487 }
1488
1489 /**
1490 * Instances of this class keep track of intermediate state during
1491 * serialization of a single library.
1492 */
1493 class _LibrarySerializer {
1494 /**
1495 * The library to be serialized.
1496 */
1497 final LibraryElement libraryElement;
1498
1499 /**
1500 * The type provider. This is used to locate the library for `dart:core`.
1501 */
1502 final TypeProvider typeProvider;
1503
1504 /**
1505 * Indicates whether the element model being serialized was analyzed using
1506 * strong mode.
1507 */
1508 final bool strongMode;
1509
1510 /**
1511 * Map from [LibraryElement] to the index of the entry in the "dependency
1512 * table" that refers to it.
1513 */
1514 final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{};
1515
1516 /**
1517 * The "dependency table". This is the list of objects which should be
1518 * written to [LinkedLibrary.dependencies].
1519 */
1520 final List<LinkedDependencyBuilder> dependencies =
1521 <LinkedDependencyBuilder>[];
1522
1523 /**
1524 * The linked portion of the "imports table". This is the list of ints
1525 * which should be written to [LinkedLibrary.imports].
1526 */
1527 final List<int> linkedImports = <int>[];
1528
1529 /**
1530 * The linked portion of the "exports table". This is the list of ints
1531 * which should be written to [LinkedLibrary.exports].
1532 */
1533 final List<int> linkedExports = <int>[];
1534
1535 /**
1536 * Set of libraries which have been seen so far while visiting the transitive
1537 * closure of exports.
1538 */
1539 final Set<LibraryElement> librariesAddedToTransitiveExportClosure =
1540 new Set<LibraryElement>();
1541
1542 /**
1543 * Map from imported element to the prefix which may be used to refer to that
1544 * element; elements for which no prefix is needed are absent from this map.
1545 */
1546 final Map<Element, PrefixElement> prefixMap = <Element, PrefixElement>{};
1547
1548 /**
1549 * List of serializers for the compilation units constituting this library.
1550 */
1551 final List<_CompilationUnitSerializer> compilationUnitSerializers =
1552 <_CompilationUnitSerializer>[];
1553
1554 _LibrarySerializer(this.libraryElement, this.typeProvider, this.strongMode) {
1555 dependencies.add(new LinkedDependencyBuilder());
1556 dependencyMap[libraryElement] = 0;
1557 }
1558
1559 /**
1560 * Retrieve a list of the Sources for the compilation units in the library.
1561 */
1562 List<Source> get unitSources => compilationUnitSerializers
1563 .map((_CompilationUnitSerializer s) => s.unitSource)
1564 .toList();
1565
1566 /**
1567 * Retrieve a list of the URIs for the compilation units in the library.
1568 */
1569 List<String> get unitUris => compilationUnitSerializers
1570 .map((_CompilationUnitSerializer s) => s.unitUri)
1571 .toList();
1572
1573 /**
1574 * Retrieve a list of the [UnlinkedUnitBuilder]s for the compilation units in
1575 * the library.
1576 */
1577 List<UnlinkedUnitBuilder> get unlinkedUnits => compilationUnitSerializers
1578 .map((_CompilationUnitSerializer s) => s.unlinkedUnit)
1579 .toList();
1580
1581 /**
1582 * Add [exportedLibrary] (and the transitive closure of all libraries it
1583 * exports) to the dependency table ([LinkedLibrary.dependencies]).
1584 */
1585 void addTransitiveExportClosure(LibraryElement exportedLibrary) {
1586 if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) {
1587 serializeDependency(exportedLibrary);
1588 for (LibraryElement transitiveExport
1589 in exportedLibrary.exportedLibraries) {
1590 addTransitiveExportClosure(transitiveExport);
1591 }
1592 }
1593 }
1594
1595 /**
1596 * Fill in [prefixMap] using information from [libraryElement.imports].
1597 */
1598 void computePrefixMap() {
1599 for (ImportElement import in libraryElement.imports) {
1600 if (import.prefix == null) {
1601 continue;
1602 }
1603 import.importedLibrary.exportNamespace.definedNames
1604 .forEach((String name, Element e) {
1605 if (new NameFilter.forNamespaceCombinators(import.combinators)
1606 .accepts(name)) {
1607 prefixMap[e] = import.prefix;
1608 }
1609 });
1610 }
1611 }
1612
1613 /**
1614 * Return the index of the entry in the dependency table
1615 * ([LinkedLibrary.dependencies]) for the given [dependentLibrary]. A new
1616 * entry is added to the table if necessary to satisfy the request.
1617 */
1618 int serializeDependency(LibraryElement dependentLibrary) {
1619 return dependencyMap.putIfAbsent(dependentLibrary, () {
1620 int index = dependencies.length;
1621 List<String> parts = dependentLibrary.parts
1622 .map((CompilationUnitElement e) => e.source.uri.toString())
1623 .toList();
1624 dependencies.add(new LinkedDependencyBuilder(
1625 uri: dependentLibrary.source.uri.toString(), parts: parts));
1626 return index;
1627 });
1628 }
1629
1630 /**
1631 * Serialize the whole library element into a [LinkedLibrary]. Should be
1632 * called exactly once for each instance of [_LibrarySerializer].
1633 *
1634 * The unlinked compilation units are stored in [unlinkedUnits], and their
1635 * absolute URIs are stored in [unitUris].
1636 */
1637 LinkedLibraryBuilder serializeLibrary() {
1638 computePrefixMap();
1639 LinkedLibraryBuilder pb = new LinkedLibraryBuilder();
1640 for (ExportElement exportElement in libraryElement.exports) {
1641 addTransitiveExportClosure(exportElement.exportedLibrary);
1642 linkedExports.add(serializeDependency(exportElement.exportedLibrary));
1643 }
1644 for (ImportElement importElement in libraryElement.imports) {
1645 addTransitiveExportClosure(importElement.importedLibrary);
1646 linkedImports.add(serializeDependency(importElement.importedLibrary));
1647 }
1648 compilationUnitSerializers.add(new _CompilationUnitSerializer(
1649 this, libraryElement.definingCompilationUnit, 0));
1650 for (int i = 0; i < libraryElement.parts.length; i++) {
1651 compilationUnitSerializers.add(
1652 new _CompilationUnitSerializer(this, libraryElement.parts[i], i + 1));
1653 }
1654 for (_CompilationUnitSerializer compilationUnitSerializer
1655 in compilationUnitSerializers) {
1656 compilationUnitSerializer.addCompilationUnitElements();
1657 }
1658 pb.units = compilationUnitSerializers
1659 .map((_CompilationUnitSerializer s) => s.linkedUnit)
1660 .toList();
1661 pb.dependencies = dependencies;
1662 pb.numPrelinkedDependencies = dependencies.length;
1663 for (_CompilationUnitSerializer compilationUnitSerializer
1664 in compilationUnitSerializers) {
1665 compilationUnitSerializer.createLinkedInfo();
1666 }
1667 pb.importDependencies = linkedImports;
1668 pb.exportDependencies = linkedExports;
1669 List<String> exportedNames =
1670 libraryElement.exportNamespace.definedNames.keys.toList();
1671 exportedNames.sort();
1672 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
1673 for (String name in exportedNames) {
1674 if (libraryElement.publicNamespace.definedNames.containsKey(name)) {
1675 continue;
1676 }
1677 Element element = libraryElement.exportNamespace.get(name);
1678 LibraryElement dependentLibrary = element.library;
1679 CompilationUnitElement unitElement =
1680 element.getAncestor((Element e) => e is CompilationUnitElement);
1681 int unit = dependentLibrary.units.indexOf(unitElement);
1682 assert(unit != -1);
1683 ReferenceKind kind = _getReferenceKind(element);
1684 exportNames.add(new LinkedExportNameBuilder(
1685 name: name,
1686 dependency: serializeDependency(dependentLibrary),
1687 unit: unit,
1688 kind: kind));
1689 }
1690 pb.exportNames = exportNames;
1691 return pb;
1692 }
1693 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/prelinker_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698