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

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

Issue 1740923002: Propertly summarize LUB function types. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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 'dart:convert'; 7 import 'dart:convert';
8 8
9 import 'package:analyzer/dart/element/element.dart'; 9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/dart/element/type.dart'; 10 import 'package:analyzer/dart/element/type.dart';
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 */ 233 */
234 int unresolvedReferenceIndex = null; 234 int unresolvedReferenceIndex = null;
235 235
236 /** 236 /**
237 * Index into the "references table" representing the "bottom" type, if such 237 * Index into the "references table" representing the "bottom" type, if such
238 * an index exists. `null` if no such entry has been made in the references 238 * an index exists. `null` if no such entry has been made in the references
239 * table yet. 239 * table yet.
240 */ 240 */
241 int bottomReferenceIndex = null; 241 int bottomReferenceIndex = null;
242 242
243 /**
244 * If `true`, we are currently generating linked references, so new
245 * references will be not stored in [unlinkedReferences].
246 */
247 bool buildingLinkedReferences = false;
248
243 _CompilationUnitSerializer( 249 _CompilationUnitSerializer(
244 this.librarySerializer, this.compilationUnit, this.unitNum); 250 this.librarySerializer, this.compilationUnit, this.unitNum);
245 251
246 /** 252 /**
247 * Source object for the compilation unit. 253 * Source object for the compilation unit.
248 */ 254 */
249 Source get unitSource => compilationUnit.source; 255 Source get unitSource => compilationUnit.source;
250 256
251 /** 257 /**
252 * Add all classes, enums, typedefs, executables, and top level variables 258 * Add all classes, enums, typedefs, executables, and top level variables
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 unlinkedUnit.references = unlinkedReferences; 371 unlinkedUnit.references = unlinkedReferences;
366 linkedUnit.references = linkedReferences; 372 linkedUnit.references = linkedReferences;
367 unitUri = compilationUnit.source.uri.toString(); 373 unitUri = compilationUnit.source.uri.toString();
368 } 374 }
369 375
370 /** 376 /**
371 * Create the [LinkedUnit.types] table based on deferred types that were 377 * Create the [LinkedUnit.types] table based on deferred types that were
372 * found during [addCompilationUnitElements]. 378 * found during [addCompilationUnitElements].
373 */ 379 */
374 void createLinkedTypes() { 380 void createLinkedTypes() {
381 buildingLinkedReferences = true;
375 linkedUnit.types = deferredLinkedTypes 382 linkedUnit.types = deferredLinkedTypes
376 .map((_SerializeTypeRef closure) => closure()) 383 .map((_SerializeTypeRef closure) => closure())
377 .toList(); 384 .toList();
385 buildingLinkedReferences = false;
378 } 386 }
379 387
380 /** 388 /**
381 * Compute the appropriate De Bruijn index to represent the given type 389 * Compute the appropriate De Bruijn index to represent the given type
382 * parameter [type]. 390 * parameter [type].
383 */ 391 */
384 int findTypeParameterIndex(TypeParameterType type, Element context) { 392 int findTypeParameterIndex(TypeParameterType type, Element context) {
385 Element originalContext = context; 393 Element originalContext = context;
386 int index = 0; 394 int index = 0;
387 while (context != null) { 395 while (context != null) {
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 } 784 }
777 785
778 /** 786 /**
779 * Serialize the given [parameter] into an [UnlinkedParam]. 787 * Serialize the given [parameter] into an [UnlinkedParam].
780 */ 788 */
781 UnlinkedParamBuilder serializeParam(ParameterElement parameter, 789 UnlinkedParamBuilder serializeParam(ParameterElement parameter,
782 [Element context]) { 790 [Element context]) {
783 context ??= parameter; 791 context ??= parameter;
784 UnlinkedParamBuilder b = new UnlinkedParamBuilder(); 792 UnlinkedParamBuilder b = new UnlinkedParamBuilder();
785 b.name = parameter.name; 793 b.name = parameter.name;
786 b.nameOffset = parameter.nameOffset; 794 b.nameOffset = parameter.nameOffset >= 0 ? parameter.nameOffset : 0;
787 switch (parameter.parameterKind) { 795 switch (parameter.parameterKind) {
788 case ParameterKind.REQUIRED: 796 case ParameterKind.REQUIRED:
789 b.kind = UnlinkedParamKind.required; 797 b.kind = UnlinkedParamKind.required;
790 break; 798 break;
791 case ParameterKind.POSITIONAL: 799 case ParameterKind.POSITIONAL:
792 b.kind = UnlinkedParamKind.positional; 800 b.kind = UnlinkedParamKind.positional;
793 break; 801 break;
794 case ParameterKind.NAMED: 802 case ParameterKind.NAMED:
795 b.kind = UnlinkedParamKind.named; 803 b.kind = UnlinkedParamKind.named;
796 break; 804 break;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 /** 850 /**
843 * Serialize the given [prefix] into an index into the references table. 851 * Serialize the given [prefix] into an index into the references table.
844 */ 852 */
845 int serializePrefix(PrefixElement element) { 853 int serializePrefix(PrefixElement element) {
846 return referenceMap.putIfAbsent(element, 854 return referenceMap.putIfAbsent(element,
847 () => serializeUnlinkedReference(element.name, ReferenceKind.prefix)); 855 () => serializeUnlinkedReference(element.name, ReferenceKind.prefix));
848 } 856 }
849 857
850 /** 858 /**
851 * Compute the reference index which should be stored in a [EntityRef]. 859 * Compute the reference index which should be stored in a [EntityRef].
852 *
853 * If [linked] is true, and a new reference has to be created, the reference
854 * will only be stored in [linkedReferences].
855 */ 860 */
856 int serializeReferenceForType(DartType type, bool linked) { 861 int serializeReferenceForType(DartType type) {
857 Element element = type.element; 862 Element element = type.element;
858 LibraryElement dependentLibrary = element?.library; 863 LibraryElement dependentLibrary = element?.library;
859 if (dependentLibrary == null) { 864 if (dependentLibrary == null) {
860 if (type.isBottom) { 865 if (type.isBottom) {
861 // References to the "bottom" type are always implicit, since there is 866 // References to the "bottom" type are always implicit, since there is
862 // no way to explicitly refer to the "bottom" type. Therefore they 867 // no way to explicitly refer to the "bottom" type. Therefore they
863 // should always be linked. 868 // should always be linked.
864 assert(linked); 869 assert(buildingLinkedReferences);
865 return serializeBottomReference(); 870 return serializeBottomReference();
866 } 871 }
867 assert(type.isDynamic || type.isVoid); 872 assert(type.isDynamic || type.isVoid);
868 if (type is UndefinedTypeImpl) { 873 if (type is UndefinedTypeImpl) {
869 return serializeUnresolvedReference(); 874 return serializeUnresolvedReference();
870 } 875 }
871 // Note: for a type which is truly `dynamic` or `void`, fall through to 876 // Note: for a type which is truly `dynamic` or `void`, fall through to
872 // use [_getElementReferenceId]. 877 // use [_getElementReferenceId].
873 } 878 }
874 return _getElementReferenceId(element, linked: linked); 879 return _getElementReferenceId(element);
875 } 880 }
876 881
877 /** 882 /**
878 * Serialize the given [typedefElement], creating an [UnlinkedTypedef]. 883 * Serialize the given [typedefElement], creating an [UnlinkedTypedef].
879 */ 884 */
880 UnlinkedTypedefBuilder serializeTypedef( 885 UnlinkedTypedefBuilder serializeTypedef(
881 FunctionTypeAliasElement typedefElement) { 886 FunctionTypeAliasElement typedefElement) {
882 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder(); 887 UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
883 b.name = typedefElement.name; 888 b.name = typedefElement.name;
884 b.nameOffset = typedefElement.nameOffset; 889 b.nameOffset = typedefElement.nameOffset;
(...skipping 16 matching lines...) Expand all
901 b.nameOffset = typeParameter.nameOffset; 906 b.nameOffset = typeParameter.nameOffset;
902 if (typeParameter.bound != null) { 907 if (typeParameter.bound != null) {
903 b.bound = serializeTypeRef(typeParameter.bound, typeParameter); 908 b.bound = serializeTypeRef(typeParameter.bound, typeParameter);
904 } 909 }
905 b.annotations = serializeAnnotations(typeParameter); 910 b.annotations = serializeAnnotations(typeParameter);
906 return b; 911 return b;
907 } 912 }
908 913
909 /** 914 /**
910 * Serialize the given [type] into a [EntityRef]. If [slot] is provided, 915 * Serialize the given [type] into a [EntityRef]. If [slot] is provided,
911 * it should be included in the [EntityRef]. If [linked] is true, any 916 * it should be included in the [EntityRef].
912 * references that are created will be populated into [linkedReferences] but
913 * not [unlinkedReferences].
914 * 917 *
915 * [context] is the element within which the [EntityRef] will be 918 * [context] is the element within which the [EntityRef] will be
916 * interpreted; this is used to serialize type parameters. 919 * interpreted; this is used to serialize type parameters.
917 */ 920 */
918 EntityRefBuilder serializeTypeRef(DartType type, Element context, 921 EntityRefBuilder serializeTypeRef(DartType type, Element context,
919 {bool linked: false, int slot}) { 922 {int slot}) {
923 if (slot != null) {
924 assert(buildingLinkedReferences);
925 }
920 EntityRefBuilder b = new EntityRefBuilder(slot: slot); 926 EntityRefBuilder b = new EntityRefBuilder(slot: slot);
927 Element typeElement = type.element;
921 if (type is TypeParameterType) { 928 if (type is TypeParameterType) {
922 b.paramReference = findTypeParameterIndex(type, context); 929 b.paramReference = findTypeParameterIndex(type, context);
930 } else if (type is FunctionType &&
931 typeElement is FunctionElement &&
932 typeElement.enclosingElement == null) {
933 b.syntheticReturnType =
934 serializeTypeRef(typeElement.returnType, typeElement);
935 b.syntheticParams = typeElement.parameters
936 .map((ParameterElement param) => serializeParam(param, context))
937 .toList();
923 } else { 938 } else {
924 if (type is FunctionType && 939 if (type is FunctionType &&
925 type.element.enclosingElement is ParameterElement) { 940 typeElement.enclosingElement is ParameterElement) {
926 // Code cannot refer to function types implicitly defined by parameters 941 // Code cannot refer to function types implicitly defined by parameters
927 // directly, so if we get here, we must be serializing a linked 942 // directly, so if we get here, we must be serializing a linked
928 // reference from type inference. 943 // reference from type inference.
929 assert(linked); 944 assert(buildingLinkedReferences);
930 ParameterElement parameterElement = type.element.enclosingElement; 945 ParameterElement parameterElement = typeElement.enclosingElement;
931 while (true) { 946 while (true) {
932 Element parent = parameterElement.enclosingElement; 947 Element parent = parameterElement.enclosingElement;
933 if (parent is ExecutableElement) { 948 if (parent is ExecutableElement) {
934 Element grandParent = parent.enclosingElement; 949 Element grandParent = parent.enclosingElement;
935 b.implicitFunctionTypeIndices 950 b.implicitFunctionTypeIndices
936 .insert(0, parent.parameters.indexOf(parameterElement)); 951 .insert(0, parent.parameters.indexOf(parameterElement));
937 if (grandParent is ParameterElement) { 952 if (grandParent is ParameterElement) {
938 // Function-typed parameter inside a function-typed parameter. 953 // Function-typed parameter inside a function-typed parameter.
939 parameterElement = grandParent; 954 parameterElement = grandParent;
940 continue; 955 continue;
941 } else { 956 } else {
942 // Function-typed parameter inside a top level function or method. 957 // Function-typed parameter inside a top level function or method.
943 b.reference = _getElementReferenceId(parent, linked: linked); 958 b.reference = _getElementReferenceId(parent);
944 break; 959 break;
945 } 960 }
946 } else { 961 } else {
947 throw new StateError( 962 throw new StateError(
948 'Unexpected element enclosing parameter: ${parent.runtimeType}') ; 963 'Unexpected element enclosing parameter: ${parent.runtimeType}') ;
949 } 964 }
950 } 965 }
951 } else { 966 } else {
952 b.reference = serializeReferenceForType(type, linked); 967 b.reference = serializeReferenceForType(type);
953 } 968 }
954 List<DartType> typeArguments = getTypeArguments(type); 969 List<DartType> typeArguments = getTypeArguments(type);
955 if (typeArguments != null) { 970 if (typeArguments != null) {
956 // Trailing type arguments of type 'dynamic' should be omitted. 971 // Trailing type arguments of type 'dynamic' should be omitted.
957 int numArgsToSerialize = typeArguments.length; 972 int numArgsToSerialize = typeArguments.length;
958 while (numArgsToSerialize > 0 && 973 while (numArgsToSerialize > 0 &&
959 typeArguments[numArgsToSerialize - 1].isDynamic) { 974 typeArguments[numArgsToSerialize - 1].isDynamic) {
960 --numArgsToSerialize; 975 --numArgsToSerialize;
961 } 976 }
962 if (numArgsToSerialize > 0) { 977 if (numArgsToSerialize > 0) {
963 List<EntityRefBuilder> serializedArguments = <EntityRefBuilder>[]; 978 List<EntityRefBuilder> serializedArguments = <EntityRefBuilder>[];
964 for (int i = 0; i < numArgsToSerialize; i++) { 979 for (int i = 0; i < numArgsToSerialize; i++) {
965 serializedArguments.add( 980 serializedArguments
966 serializeTypeRef(typeArguments[i], context, linked: linked)); 981 .add(serializeTypeRef(typeArguments[i], context));
967 } 982 }
968 b.typeArguments = serializedArguments; 983 b.typeArguments = serializedArguments;
969 } 984 }
970 } 985 }
971 } 986 }
972 return b; 987 return b;
973 } 988 }
974 989
975 /** 990 /**
976 * Create a new entry in the references table ([UnlinkedLibrary.references] 991 * Create a new entry in the references table ([UnlinkedLibrary.references]
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 * [linkedTypes] so that once the compilation unit has been fully visited, 1090 * [linkedTypes] so that once the compilation unit has been fully visited,
1076 * it will be serialized to [LinkedUnit.types]. 1091 * it will be serialized to [LinkedUnit.types].
1077 * 1092 *
1078 * [context] is the element within which the slot id will appear; this is 1093 * [context] is the element within which the slot id will appear; this is
1079 * used to serialize type parameters. 1094 * used to serialize type parameters.
1080 */ 1095 */
1081 int storeLinkedType(DartType type, Element context) { 1096 int storeLinkedType(DartType type, Element context) {
1082 int slot = ++numSlots; 1097 int slot = ++numSlots;
1083 if (type != null) { 1098 if (type != null) {
1084 deferredLinkedTypes 1099 deferredLinkedTypes
1085 .add(() => serializeTypeRef(type, context, linked: true, slot: slot)); 1100 .add(() => serializeTypeRef(type, context, slot: slot));
1086 } 1101 }
1087 return slot; 1102 return slot;
1088 } 1103 }
1089 1104
1090 int _getElementReferenceId(Element element, {bool linked: false}) { 1105 int _getElementReferenceId(Element element) {
1091 return referenceMap.putIfAbsent(element, () { 1106 return referenceMap.putIfAbsent(element, () {
1092 LibraryElement dependentLibrary = librarySerializer.libraryElement; 1107 LibraryElement dependentLibrary = librarySerializer.libraryElement;
1093 int unit = 0; 1108 int unit = 0;
1094 Element enclosingElement; 1109 Element enclosingElement;
1095 if (element != null) { 1110 if (element != null) {
1096 enclosingElement = element.enclosingElement; 1111 enclosingElement = element.enclosingElement;
1097 if (enclosingElement is CompilationUnitElement) { 1112 if (enclosingElement is CompilationUnitElement) {
1098 dependentLibrary = enclosingElement.library; 1113 dependentLibrary = enclosingElement.library;
1099 unit = dependentLibrary.units.indexOf(enclosingElement); 1114 unit = dependentLibrary.units.indexOf(enclosingElement);
1100 assert(unit != -1); 1115 assert(unit != -1);
1101 } 1116 }
1102 } 1117 }
1103 ReferenceKind kind = _getReferenceKind(element); 1118 ReferenceKind kind = _getReferenceKind(element);
1104 String name = element == null ? 'void' : element.name; 1119 String name = element == null ? 'void' : element.name;
1105 int index; 1120 int index;
1106 LinkedReferenceBuilder linkedReference; 1121 LinkedReferenceBuilder linkedReference;
1107 if (linked) { 1122 if (buildingLinkedReferences) {
1108 linkedReference = 1123 linkedReference =
1109 new LinkedReferenceBuilder(kind: kind, unit: unit, name: name); 1124 new LinkedReferenceBuilder(kind: kind, unit: unit, name: name);
1110 if (enclosingElement != null && 1125 if (enclosingElement != null &&
1111 enclosingElement is! CompilationUnitElement) { 1126 enclosingElement is! CompilationUnitElement) {
1112 linkedReference.containingReference = 1127 linkedReference.containingReference =
1113 _getElementReferenceId(enclosingElement, linked: linked); 1128 _getElementReferenceId(enclosingElement);
1114 if (enclosingElement is ClassElement) { 1129 if (enclosingElement is ClassElement) {
1115 // Nothing to do. 1130 // Nothing to do.
1116 } else if (enclosingElement is ExecutableElement) { 1131 } else if (enclosingElement is ExecutableElement) {
1117 if (element is FunctionElement) { 1132 if (element is FunctionElement) {
1118 assert(enclosingElement.functions.contains(element)); 1133 assert(enclosingElement.functions.contains(element));
1119 linkedReference.localIndex = 1134 linkedReference.localIndex =
1120 enclosingElement.functions.indexOf(element); 1135 enclosingElement.functions.indexOf(element);
1121 } else if (element is LocalVariableElement) { 1136 } else if (element is LocalVariableElement) {
1122 assert(enclosingElement.localVariables.contains(element)); 1137 assert(enclosingElement.localVariables.contains(element));
1123 linkedReference.localIndex = 1138 linkedReference.localIndex =
(...skipping 19 matching lines...) Expand all
1143 // Figure out a prefix that may be used to refer to the given element. 1158 // Figure out a prefix that may be used to refer to the given element.
1144 // TODO(paulberry): to avoid subtle relinking inconsistencies we 1159 // TODO(paulberry): to avoid subtle relinking inconsistencies we
1145 // should use the actual prefix from the AST (a given type may be 1160 // should use the actual prefix from the AST (a given type may be
1146 // reachable via multiple prefixes), but sadly, this information is 1161 // reachable via multiple prefixes), but sadly, this information is
1147 // not recorded in the element model. 1162 // not recorded in the element model.
1148 PrefixElement prefix = librarySerializer.prefixMap[element]; 1163 PrefixElement prefix = librarySerializer.prefixMap[element];
1149 if (prefix != null) { 1164 if (prefix != null) {
1150 prefixReference = serializePrefix(prefix); 1165 prefixReference = serializePrefix(prefix);
1151 } 1166 }
1152 } else { 1167 } else {
1153 prefixReference = _getElementReferenceId(enclosing, linked: linked); 1168 prefixReference = _getElementReferenceId(enclosing);
1154 } 1169 }
1155 index = serializeUnlinkedReference(name, kind, 1170 index = serializeUnlinkedReference(name, kind,
1156 prefixReference: prefixReference, unit: unit); 1171 prefixReference: prefixReference, unit: unit);
1157 linkedReference = linkedReferences[index]; 1172 linkedReference = linkedReferences[index];
1158 } 1173 }
1159 linkedReference.dependency = 1174 linkedReference.dependency =
1160 librarySerializer.serializeDependency(dependentLibrary); 1175 librarySerializer.serializeDependency(dependentLibrary);
1161 if (element is TypeParameterizedElement) { 1176 if (element is TypeParameterizedElement) {
1162 linkedReference.numTypeParameters += element.typeParameters.length; 1177 linkedReference.numTypeParameters += element.typeParameters.length;
1163 } 1178 }
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1509 exportNames.add(new LinkedExportNameBuilder( 1524 exportNames.add(new LinkedExportNameBuilder(
1510 name: name, 1525 name: name,
1511 dependency: serializeDependency(dependentLibrary), 1526 dependency: serializeDependency(dependentLibrary),
1512 unit: unit, 1527 unit: unit,
1513 kind: kind)); 1528 kind: kind));
1514 } 1529 }
1515 pb.exportNames = exportNames; 1530 pb.exportNames = exportNames;
1516 return pb; 1531 return pb;
1517 } 1532 }
1518 } 1533 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/summary/resynthesize.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