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

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

Issue 1610043002: Add propagated types to summary files. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 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
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 'package:analyzer/dart/element/element.dart'; 7 import 'package:analyzer/dart/element/element.dart';
8 import 'package:analyzer/dart/element/type.dart'; 8 import 'package:analyzer/dart/element/type.dart';
9 import 'package:analyzer/src/dart/element/element.dart'; 9 import 'package:analyzer/src/dart/element/element.dart';
10 import 'package:analyzer/src/dart/element/type.dart'; 10 import 'package:analyzer/src/dart/element/type.dart';
(...skipping 26 matching lines...) Expand all
37 kind = ReferenceKind.classOrEnum; 37 kind = ReferenceKind.classOrEnum;
38 } else if (element is FunctionElement) { 38 } else if (element is FunctionElement) {
39 kind = ReferenceKind.topLevelFunction; 39 kind = ReferenceKind.topLevelFunction;
40 } else { 40 } else {
41 throw new Exception('Unexpected element kind: ${element.runtimeType}'); 41 throw new Exception('Unexpected element kind: ${element.runtimeType}');
42 } 42 }
43 return kind; 43 return kind;
44 } 44 }
45 45
46 /** 46 /**
47 * Type of closures used by [_LibrarySerializer] to defer generation of
48 * [TypeRefBuilder] objects until the end of serialization of a
49 * compilation unit.
50 */
51 typedef TypeRefBuilder _SerializeTypeRef();
52
53 /**
47 * Data structure holding the result of serializing a [LibraryElement]. 54 * Data structure holding the result of serializing a [LibraryElement].
48 */ 55 */
49 class LibrarySerializationResult { 56 class LibrarySerializationResult {
50 /** 57 /**
51 * Linked information the given library. 58 * Linked information the given library.
52 */ 59 */
53 final LinkedLibraryBuilder linked; 60 final LinkedLibraryBuilder linked;
54 61
55 /** 62 /**
56 * Unlinked information for the compilation units constituting the library. 63 * Unlinked information for the compilation units constituting the library.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 */ 124 */
118 List<UnlinkedReferenceBuilder> unlinkedReferences; 125 List<UnlinkedReferenceBuilder> unlinkedReferences;
119 126
120 /** 127 /**
121 * The linked portion of the "references table". This is the list of 128 * The linked portion of the "references table". This is the list of
122 * objects which should be written to [LinkedUnit.references]. 129 * objects which should be written to [LinkedUnit.references].
123 */ 130 */
124 List<LinkedReferenceBuilder> linkedReferences; 131 List<LinkedReferenceBuilder> linkedReferences;
125 132
126 /** 133 /**
134 * The number of slot ids which have been assigned to this compilation unit.
135 */
136 int numSlots = 0;
137
138 /**
139 * List of closures which should be invoked at the end of serialization of a
140 * compilation unit, to produce [LinkedUnit.types].
141 */
142 final List<_SerializeTypeRef> deferredLinkedTypes = <_SerializeTypeRef>[];
143
144 /**
127 * Index into the "references table" representing an unresolved reference, if 145 * Index into the "references table" representing an unresolved reference, if
128 * such an index exists. `null` if no such entry has been made in the 146 * such an index exists. `null` if no such entry has been made in the
129 * references table yet. 147 * references table yet.
130 */ 148 */
131 int unresolvedReferenceIndex = null; 149 int unresolvedReferenceIndex = null;
132 150
133 _CompilationUnitSerializer( 151 _CompilationUnitSerializer(
134 this.librarySerializer, this.compilationUnit, this.unitNum); 152 this.librarySerializer, this.compilationUnit, this.unitNum);
135 153
136 /** 154 /**
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 } 260 }
243 } 261 }
244 } 262 }
245 unlinkedUnit.variables = variables; 263 unlinkedUnit.variables = variables;
246 unlinkedUnit.references = unlinkedReferences; 264 unlinkedUnit.references = unlinkedReferences;
247 linkedUnit.references = linkedReferences; 265 linkedUnit.references = linkedReferences;
248 unitUri = compilationUnit.source.uri.toString(); 266 unitUri = compilationUnit.source.uri.toString();
249 } 267 }
250 268
251 /** 269 /**
270 * Create the [LinkedUnit.types] table based on deferred types that were
271 * found during [addCompilationUnitElements].
272 */
273 void createLinkedTypes() {
274 linkedUnit.types = deferredLinkedTypes
275 .map((_SerializeTypeRef closure) => closure())
276 .toList();
277 }
278
279 /**
252 * Compute the appropriate De Bruijn index to represent the given type 280 * Compute the appropriate De Bruijn index to represent the given type
253 * parameter [type]. 281 * parameter [type].
254 */ 282 */
255 int findTypeParameterIndex(TypeParameterType type, Element context) { 283 int findTypeParameterIndex(TypeParameterType type, Element context) {
256 int index = 0; 284 int index = 0;
257 while (context != null) { 285 while (context != null) {
258 List<TypeParameterElement> typeParameters; 286 List<TypeParameterElement> typeParameters;
259 if (context is ClassElement) { 287 if (context is ClassElement) {
260 typeParameters = context.typeParameters; 288 typeParameters = context.typeParameters;
261 } else if (context is FunctionTypeAliasElement) { 289 } else if (context is FunctionTypeAliasElement) {
262 typeParameters = context.typeParameters; 290 typeParameters = context.typeParameters;
263 } else if (context is ExecutableElement) { 291 } else if (context is ExecutableElement) {
264 typeParameters = context.typeParameters; 292 typeParameters = context.typeParameters;
265 } 293 }
266 if (typeParameters != null) { 294 if (typeParameters != null) {
267 for (int i = 0; i < typeParameters.length; i++) { 295 for (int i = 0; i < typeParameters.length; i++) {
268 TypeParameterElement param = typeParameters[i]; 296 TypeParameterElement param = typeParameters[i];
269 if (param == type.element) { 297 if (param == type.element) {
270 return index + typeParameters.length - i; 298 return index + typeParameters.length - i;
271 } 299 }
272 } 300 }
273 index += typeParameters.length; 301 index += typeParameters.length;
274 } 302 }
275 context = context.enclosingElement; 303 context = context.enclosingElement;
276 } 304 }
277 throw new StateError('Unbound type parameter $type'); 305 throw new StateError('Unbound type parameter $type');
278 } 306 }
279 307
280 /** 308 /**
309 * Get the type arguments for the given [type], or `null` if the type has no
310 * type arguments.
311 *
312 * TODO(paulberry): consider adding an abstract getter to [DartType] to do
313 * this.
314 */
315 List<DartType> getTypeArguments(DartType type) {
316 if (type is InterfaceType) {
317 return type.typeArguments;
318 } else if (type is FunctionType) {
319 return type.typeArguments;
320 } else {
321 return null;
322 }
323 }
324
325 /**
281 * Serialize the given [classElement], creating an [UnlinkedClass]. 326 * Serialize the given [classElement], creating an [UnlinkedClass].
282 */ 327 */
283 UnlinkedClassBuilder serializeClass(ClassElement classElement) { 328 UnlinkedClassBuilder serializeClass(ClassElement classElement) {
284 UnlinkedClassBuilder b = new UnlinkedClassBuilder(); 329 UnlinkedClassBuilder b = new UnlinkedClassBuilder();
285 b.name = classElement.name; 330 b.name = classElement.name;
286 b.nameOffset = classElement.nameOffset; 331 b.nameOffset = classElement.nameOffset;
287 b.typeParameters = 332 b.typeParameters =
288 classElement.typeParameters.map(serializeTypeParam).toList(); 333 classElement.typeParameters.map(serializeTypeParam).toList();
289 if (classElement.supertype == null) { 334 if (classElement.supertype == null) {
290 b.hasNoSupertype = true; 335 b.hasNoSupertype = true;
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 assert(unlinkedReferences.length == linkedReferences.length); 573 assert(unlinkedReferences.length == linkedReferences.length);
529 int index = unlinkedReferences.length; 574 int index = unlinkedReferences.length;
530 unlinkedReferences.add(new UnlinkedReferenceBuilder(name: element.name)); 575 unlinkedReferences.add(new UnlinkedReferenceBuilder(name: element.name));
531 linkedReferences 576 linkedReferences
532 .add(new LinkedReferenceBuilder(kind: ReferenceKind.prefix)); 577 .add(new LinkedReferenceBuilder(kind: ReferenceKind.prefix));
533 return index; 578 return index;
534 }); 579 });
535 } 580 }
536 581
537 /** 582 /**
583 * Compute the reference index which should be stored in a [TypeRef].
584 *
585 * If [linked] is true, and a new reference has to be created, the reference
586 * will only be stored in [linkedReferences].
587 */
588 int serializeReferenceForType(DartType type, bool linked) {
589 Element element = type.element;
590 LibraryElement dependentLibrary = element.library;
591 if (dependentLibrary == null) {
592 assert(type.isDynamic);
593 if (type is UndefinedTypeImpl) {
594 return serializeUnresolvedReference();
595 } else {
596 return serializeDynamicReference();
597 }
598 } else {
599 return _getElementReferenceId(element, linked: linked);
600 }
601 }
602
603 /**
538 * Serialize the given [typedefElement], creating an [UnlinkedTypedef]. 604 * Serialize the given [typedefElement], creating an [UnlinkedTypedef].
539 */ 605 */
540 UnlinkedTypedefBuilder serializeTypedef( 606 UnlinkedTypedefBuilder serializeTypedef(
541 FunctionTypeAliasElement typedefElement) { 607 FunctionTypeAliasElement typedefElement) {
542 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder(); 608 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
543 b.name = typedefElement.name; 609 b.name = typedefElement.name;
544 b.nameOffset = typedefElement.nameOffset; 610 b.nameOffset = typedefElement.nameOffset;
545 b.typeParameters = 611 b.typeParameters =
546 typedefElement.typeParameters.map(serializeTypeParam).toList(); 612 typedefElement.typeParameters.map(serializeTypeParam).toList();
547 if (!typedefElement.returnType.isVoid) { 613 if (!typedefElement.returnType.isVoid) {
(...skipping 13 matching lines...) Expand all
561 UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder(); 627 UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
562 b.name = typeParameter.name; 628 b.name = typeParameter.name;
563 b.nameOffset = typeParameter.nameOffset; 629 b.nameOffset = typeParameter.nameOffset;
564 if (typeParameter.bound != null) { 630 if (typeParameter.bound != null) {
565 b.bound = serializeTypeRef(typeParameter.bound, typeParameter); 631 b.bound = serializeTypeRef(typeParameter.bound, typeParameter);
566 } 632 }
567 return b; 633 return b;
568 } 634 }
569 635
570 /** 636 /**
571 * Serialize the given [type] into a [TypeRef]. 637 * Serialize the given [type] into a [TypeRef]. If [slot] is provided,
638 * it should be included in the [TypeRef]. If [linked] is true, any
639 * references that are created will be populated into [linkedReferences] but
640 * [not [unlinkedReferences].
641 *
642 * [context] is the element within which the [TypeRef] will be
643 * interpreted; this is used to serialize type parameters.
572 */ 644 */
573 TypeRefBuilder serializeTypeRef(DartType type, Element context) { 645 TypeRefBuilder serializeTypeRef(DartType type, Element context,
574 TypeRefBuilder b = new TypeRefBuilder(); 646 {bool linked: false, int slot}) {
647 TypeRefBuilder b = new TypeRefBuilder(slot: slot);
575 if (type is TypeParameterType) { 648 if (type is TypeParameterType) {
576 b.paramReference = findTypeParameterIndex(type, context); 649 b.paramReference = findTypeParameterIndex(type, context);
577 } else { 650 } else {
578 Element element = type.element; 651 b.reference = serializeReferenceForType(type, linked);
579 LibraryElement dependentLibrary = element.library; 652 List<DartType> typeArguments = getTypeArguments(type);
580 if (dependentLibrary == null) {
581 assert(type.isDynamic);
582 if (type is UndefinedTypeImpl) {
583 b.reference = serializeUnresolvedReference();
584 } else {
585 b.reference = serializeDynamicReference();
586 }
587 } else {
588 b.reference = _getElementReferenceId(element);
589 }
590 List<DartType> typeArguments;
591 if (type is InterfaceType) {
592 typeArguments = type.typeArguments;
593 } else if (type is FunctionType) {
594 typeArguments = type.typeArguments;
595 }
596 if (typeArguments != null) { 653 if (typeArguments != null) {
597 // Trailing type arguments of type 'dynamic' should be omitted. 654 // Trailing type arguments of type 'dynamic' should be omitted.
598 int numArgsToSerialize = typeArguments.length; 655 int numArgsToSerialize = typeArguments.length;
599 while (numArgsToSerialize > 0 && 656 while (numArgsToSerialize > 0 &&
600 typeArguments[numArgsToSerialize - 1].isDynamic) { 657 typeArguments[numArgsToSerialize - 1].isDynamic) {
601 --numArgsToSerialize; 658 --numArgsToSerialize;
602 } 659 }
603 if (numArgsToSerialize > 0) { 660 if (numArgsToSerialize > 0) {
604 List<TypeRefBuilder> serializedArguments = <TypeRefBuilder>[]; 661 List<TypeRefBuilder> serializedArguments = <TypeRefBuilder>[];
605 for (int i = 0; i < numArgsToSerialize; i++) { 662 for (int i = 0; i < numArgsToSerialize; i++) {
606 serializedArguments 663 serializedArguments.add(
607 .add(serializeTypeRef(typeArguments[i], context)); 664 serializeTypeRef(typeArguments[i], context, linked: linked));
608 } 665 }
609 b.typeArguments = serializedArguments; 666 b.typeArguments = serializedArguments;
610 } 667 }
611 } 668 }
612 } 669 }
613 return b; 670 return b;
614 } 671 }
615 672
616 /** 673 /**
617 * Return the index of the entry in the references table 674 * Return the index of the entry in the references table
(...skipping 30 matching lines...) Expand all
648 b.isConst = variable.isConst; 705 b.isConst = variable.isConst;
649 b.hasImplicitType = variable.hasImplicitType; 706 b.hasImplicitType = variable.hasImplicitType;
650 b.documentationComment = serializeDocumentation(variable); 707 b.documentationComment = serializeDocumentation(variable);
651 if (variable.isConst && variable is ConstVariableElement) { 708 if (variable.isConst && variable is ConstVariableElement) {
652 ConstVariableElement constVariable = variable as ConstVariableElement; 709 ConstVariableElement constVariable = variable as ConstVariableElement;
653 Expression initializer = constVariable.constantInitializer; 710 Expression initializer = constVariable.constantInitializer;
654 if (initializer != null) { 711 if (initializer != null) {
655 b.constExpr = serializeConstExpr(initializer); 712 b.constExpr = serializeConstExpr(initializer);
656 } 713 }
657 } 714 }
715 if (b.isFinal || b.isConst) {
716 b.propagatedTypeSlot = storeLinkedType(variable.propagatedType, variable);
717 } else {
718 // Variable is not propagable.
719 assert(variable.propagatedType == null);
720 }
658 return b; 721 return b;
659 } 722 }
660 723
661 int _getElementReferenceId(Element element) { 724 /**
725 * Create a slot id for the given [type] (which may be either a propagated
726 * type or an inferred type). If [type] is not `null`, it is stored in
727 * [linkedTypes] so that once the compilation unit has been fully visited,
728 * it will be serialized to [LinkedUnit.types].
729 *
730 * [context] is the element within which the slot id will appear; this is
731 * used to serialize type parameters.
732 */
733 int storeLinkedType(DartType type, Element context) {
734 int slot = ++numSlots;
735 if (type != null) {
736 deferredLinkedTypes
737 .add(() => serializeTypeRef(type, context, linked: true, slot: slot));
738 }
739 return slot;
740 }
741
742 int _getElementReferenceId(Element element, {bool linked: false}) {
662 LibraryElement dependentLibrary = element.library; 743 LibraryElement dependentLibrary = element.library;
663 return referenceMap.putIfAbsent(element, () { 744 return referenceMap.putIfAbsent(element, () {
664 assert(unlinkedReferences.length == linkedReferences.length);
665 CompilationUnitElement unitElement = 745 CompilationUnitElement unitElement =
666 element.getAncestor((Element e) => e is CompilationUnitElement); 746 element.getAncestor((Element e) => e is CompilationUnitElement);
667 int unit = dependentLibrary.units.indexOf(unitElement); 747 int unit = dependentLibrary.units.indexOf(unitElement);
668 assert(unit != -1); 748 assert(unit != -1);
669 int numTypeParameters = 0; 749 int numTypeParameters = 0;
670 if (element is TypeParameterizedElement) { 750 if (element is TypeParameterizedElement) {
671 numTypeParameters = element.typeParameters.length; 751 numTypeParameters = element.typeParameters.length;
672 } 752 }
673 // Figure out a prefix that may be used to refer to the given type. 753 LinkedReferenceBuilder linkedReference = new LinkedReferenceBuilder(
674 // TODO(paulberry): to avoid subtle relinking inconsistencies we
675 // should use the actual prefix from the AST (a given type may be
676 // reachable via multiple prefixes), but sadly, this information is
677 // not recorded in the element model.
678 int prefixReference = 0;
679 PrefixElement prefix = librarySerializer.prefixMap[element];
680 if (prefix != null) {
681 prefixReference = serializePrefix(prefix);
682 }
683 int index = unlinkedReferences.length;
684 unlinkedReferences.add(new UnlinkedReferenceBuilder(
685 name: element.name, prefixReference: prefixReference));
686 linkedReferences.add(new LinkedReferenceBuilder(
687 dependency: librarySerializer.serializeDependency(dependentLibrary), 754 dependency: librarySerializer.serializeDependency(dependentLibrary),
688 kind: _getReferenceKind(element), 755 kind: _getReferenceKind(element),
689 unit: unit, 756 unit: unit,
690 numTypeParameters: numTypeParameters)); 757 numTypeParameters: numTypeParameters);
758 if (linked) {
759 linkedReference.name = element.name;
760 } else {
761 assert(unlinkedReferences.length == linkedReferences.length);
762 // Figure out a prefix that may be used to refer to the given type.
763 // TODO(paulberry): to avoid subtle relinking inconsistencies we
764 // should use the actual prefix from the AST (a given type may be
765 // reachable via multiple prefixes), but sadly, this information is
766 // not recorded in the element model.
767 int prefixReference = 0;
768 PrefixElement prefix = librarySerializer.prefixMap[element];
769 if (prefix != null) {
770 prefixReference = serializePrefix(prefix);
771 }
772 unlinkedReferences.add(new UnlinkedReferenceBuilder(
773 name: element.name, prefixReference: prefixReference));
774 }
775 int index = linkedReferences.length;
776 linkedReferences.add(linkedReference);
691 return index; 777 return index;
692 }); 778 });
693 } 779 }
694 } 780 }
695 781
696 /** 782 /**
697 * Instances of this class keep track of intermediate state during 783 * Instances of this class keep track of intermediate state during
698 * serialization of a single constant [Expression]. 784 * serialization of a single constant [Expression].
699 */ 785 */
700 class _ConstExprSerializer extends AbstractConstExprSerializer { 786 class _ConstExprSerializer extends AbstractConstExprSerializer {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 new _CompilationUnitSerializer(this, libraryElement.parts[i], i + 1)); 949 new _CompilationUnitSerializer(this, libraryElement.parts[i], i + 1));
864 } 950 }
865 for (_CompilationUnitSerializer compilationUnitSerializer 951 for (_CompilationUnitSerializer compilationUnitSerializer
866 in compilationUnitSerializers) { 952 in compilationUnitSerializers) {
867 compilationUnitSerializer.addCompilationUnitElements(); 953 compilationUnitSerializer.addCompilationUnitElements();
868 } 954 }
869 pb.units = compilationUnitSerializers 955 pb.units = compilationUnitSerializers
870 .map((_CompilationUnitSerializer s) => s.linkedUnit) 956 .map((_CompilationUnitSerializer s) => s.linkedUnit)
871 .toList(); 957 .toList();
872 pb.dependencies = dependencies; 958 pb.dependencies = dependencies;
959 pb.numPrelinkedDependencies = dependencies.length;
960 for (_CompilationUnitSerializer compilationUnitSerializer
961 in compilationUnitSerializers) {
962 compilationUnitSerializer.createLinkedTypes();
963 }
873 pb.importDependencies = linkedImports; 964 pb.importDependencies = linkedImports;
874 List<String> exportedNames = 965 List<String> exportedNames =
875 libraryElement.exportNamespace.definedNames.keys.toList(); 966 libraryElement.exportNamespace.definedNames.keys.toList();
876 exportedNames.sort(); 967 exportedNames.sort();
877 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; 968 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
878 for (String name in exportedNames) { 969 for (String name in exportedNames) {
879 if (libraryElement.publicNamespace.definedNames.containsKey(name)) { 970 if (libraryElement.publicNamespace.definedNames.containsKey(name)) {
880 continue; 971 continue;
881 } 972 }
882 Element element = libraryElement.exportNamespace.get(name); 973 Element element = libraryElement.exportNamespace.get(name);
883 LibraryElement dependentLibrary = element.library; 974 LibraryElement dependentLibrary = element.library;
884 CompilationUnitElement unitElement = 975 CompilationUnitElement unitElement =
885 element.getAncestor((Element e) => e is CompilationUnitElement); 976 element.getAncestor((Element e) => e is CompilationUnitElement);
886 int unit = dependentLibrary.units.indexOf(unitElement); 977 int unit = dependentLibrary.units.indexOf(unitElement);
887 assert(unit != -1); 978 assert(unit != -1);
888 ReferenceKind kind = _getReferenceKind(element); 979 ReferenceKind kind = _getReferenceKind(element);
889 exportNames.add(new LinkedExportNameBuilder( 980 exportNames.add(new LinkedExportNameBuilder(
890 name: name, 981 name: name,
891 dependency: serializeDependency(dependentLibrary), 982 dependency: serializeDependency(dependentLibrary),
892 unit: unit, 983 unit: unit,
893 kind: kind)); 984 kind: kind));
894 } 985 }
895 pb.exportNames = exportNames; 986 pb.exportNames = exportNames;
896 return pb; 987 return pb;
897 } 988 }
898 } 989 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/summary/summarize_ast.dart ('k') | pkg/analyzer/test/src/summary/resynthesize_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698