| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |